Windows: Defer deref of a directoryEntry
[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         if( !NT_SUCCESS( ntStatus))
1171         {
1172
1173         }
1174     }
1175
1176     return ntStatus;
1177 }
1178
1179 NTSTATUS
1180 AFSUpdateFileInformation( IN AFSFileID *ParentFid,
1181                           IN AFSObjectInfoCB *ObjectInfo,
1182                           IN GUID *AuthGroup)
1183 {
1184
1185     NTSTATUS ntStatus = STATUS_SUCCESS;
1186     AFSDeviceExt *pDeviceExt = (AFSDeviceExt *)AFSRDRDeviceObject->DeviceExtension;
1187     AFSFileUpdateCB stUpdateCB;
1188     ULONG ulResultLen = 0;
1189     AFSFileUpdateResultCB *pUpdateResultCB = NULL;
1190
1191     __Enter
1192     {
1193
1194         //
1195         // Init the control block for the request
1196         //
1197
1198         RtlZeroMemory( &stUpdateCB,
1199                        sizeof( AFSFileUpdateCB));
1200
1201         stUpdateCB.AllocationSize = ObjectInfo->EndOfFile;
1202
1203         stUpdateCB.FileAttributes = ObjectInfo->FileAttributes;
1204
1205         stUpdateCB.EaSize = ObjectInfo->EaSize;
1206
1207         stUpdateCB.ParentId = *ParentFid;
1208
1209         stUpdateCB.LastAccessTime = ObjectInfo->LastAccessTime;
1210
1211         stUpdateCB.CreateTime = ObjectInfo->CreationTime;
1212
1213         stUpdateCB.ChangeTime = ObjectInfo->ChangeTime;
1214
1215         stUpdateCB.LastWriteTime = ObjectInfo->LastWriteTime;
1216
1217         pUpdateResultCB = (AFSFileUpdateResultCB *)AFSExAllocatePoolWithTag( PagedPool,
1218                                                                              PAGE_SIZE,
1219                                                                              AFS_UPDATE_RESULT_TAG);
1220
1221         if( pUpdateResultCB == NULL)
1222         {
1223
1224             try_return( ntStatus = STATUS_INSUFFICIENT_RESOURCES);
1225         }
1226
1227         ulResultLen = PAGE_SIZE;
1228
1229         ntStatus = AFSProcessRequest( AFS_REQUEST_TYPE_UPDATE_FILE,
1230                                       AFS_REQUEST_FLAG_SYNCHRONOUS,
1231                                       AuthGroup,
1232                                       NULL,
1233                                       &ObjectInfo->FileId,
1234                                       &stUpdateCB,
1235                                       sizeof( AFSFileUpdateCB),
1236                                       pUpdateResultCB,
1237                                       &ulResultLen);
1238
1239         if( ntStatus != STATUS_SUCCESS)
1240         {
1241
1242             AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
1243                           AFS_TRACE_LEVEL_ERROR,
1244                           "AFSUpdateFileInformation failed FID %08lX-%08lX-%08lX-%08lX Status %08lX\n",
1245                           ObjectInfo->FileId.Cell,
1246                           ObjectInfo->FileId.Volume,
1247                           ObjectInfo->FileId.Vnode,
1248                           ObjectInfo->FileId.Unique,
1249                           ntStatus);
1250
1251             try_return( ntStatus);
1252         }
1253
1254         //
1255         // Update the data version
1256         //
1257
1258         ObjectInfo->DataVersion = pUpdateResultCB->DirEnum.DataVersion;
1259
1260 try_exit:
1261
1262         if( pUpdateResultCB != NULL)
1263         {
1264
1265             AFSExFreePool( pUpdateResultCB);
1266         }
1267     }
1268
1269     return ntStatus;
1270 }
1271
1272 NTSTATUS
1273 AFSNotifyDelete( IN AFSDirectoryCB *DirectoryCB,
1274                  IN BOOLEAN CheckOnly)
1275 {
1276     NTSTATUS ntStatus = STATUS_SUCCESS;
1277     ULONG ulResultLen = 0;
1278     AFSFileDeleteCB stDelete;
1279     AFSFileDeleteResultCB stDeleteResult;
1280     ULONG ulRequestFlags = AFS_REQUEST_FLAG_SYNCHRONOUS;
1281     GUID *pAuthGroup = NULL;
1282
1283     __Enter
1284     {
1285
1286         stDelete.ParentId = DirectoryCB->ObjectInformation->ParentObjectInformation->FileId;
1287
1288         stDelete.ProcessId = (ULONGLONG)PsGetCurrentProcessId();
1289
1290         ulResultLen = sizeof( AFSFileDeleteResultCB);
1291
1292         if( CheckOnly)
1293         {
1294             ulRequestFlags |= AFS_REQUEST_FLAG_CHECK_ONLY;
1295         }
1296
1297         if( DirectoryCB->ObjectInformation->Fcb != NULL)
1298         {
1299             pAuthGroup = &DirectoryCB->ObjectInformation->Fcb->AuthGroup;
1300         }
1301
1302         ntStatus = AFSProcessRequest( AFS_REQUEST_TYPE_DELETE_FILE,
1303                                       ulRequestFlags,
1304                                       pAuthGroup,
1305                                       &DirectoryCB->NameInformation.FileName,
1306                                       &DirectoryCB->ObjectInformation->FileId,
1307                                       &stDelete,
1308                                       sizeof( AFSFileDeleteCB),
1309                                       &stDeleteResult,
1310                                       &ulResultLen);
1311
1312         if( ntStatus != STATUS_SUCCESS)
1313         {
1314
1315             AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
1316                           AFS_TRACE_LEVEL_ERROR,
1317                           "AFSNotifyDelete failed FID %08lX-%08lX-%08lX-%08lX Status %08lX\n",
1318                           &DirectoryCB->ObjectInformation->FileId.Cell,
1319                           &DirectoryCB->ObjectInformation->FileId.Volume,
1320                           &DirectoryCB->ObjectInformation->FileId.Vnode,
1321                           &DirectoryCB->ObjectInformation->FileId.Unique,
1322                           ntStatus);
1323
1324             try_return( ntStatus);
1325         }
1326
1327         if( !CheckOnly)
1328         {
1329
1330             //
1331             // Update the parent data version
1332             //
1333
1334             if( DirectoryCB->ObjectInformation->ParentObjectInformation->DataVersion.QuadPart != stDeleteResult.ParentDataVersion.QuadPart)
1335             {
1336
1337                 DirectoryCB->ObjectInformation->ParentObjectInformation->Flags |= AFS_OBJECT_FLAGS_VERIFY;
1338
1339                 DirectoryCB->ObjectInformation->ParentObjectInformation->DataVersion.QuadPart = (ULONGLONG)-1;
1340             }
1341         }
1342
1343 try_exit:
1344
1345         NOTHING;
1346     }
1347
1348     return ntStatus;
1349 }
1350
1351 NTSTATUS
1352 AFSNotifyRename( IN AFSObjectInfoCB *ObjectInfo,
1353                  IN AFSObjectInfoCB *ParentObjectInfo,
1354                  IN AFSObjectInfoCB *TargetParentObjectInfo,
1355                  IN AFSDirectoryCB *DirectoryCB,
1356                  IN UNICODE_STRING *TargetName,
1357                  OUT AFSFileID  *UpdatedFID)
1358 {
1359
1360     NTSTATUS ntStatus = STATUS_SUCCESS;
1361     AFSFileRenameCB *pRenameCB = NULL;
1362     AFSFileRenameResultCB *pRenameResultCB = NULL;
1363     ULONG ulResultLen = 0;
1364     GUID *pAuthGroup = NULL;
1365
1366     __Enter
1367     {
1368
1369         //
1370         // Init the control block for the request
1371         //
1372
1373         pRenameCB = (AFSFileRenameCB *)AFSExAllocatePoolWithTag( PagedPool,
1374                                                                  PAGE_SIZE,
1375                                                                  AFS_RENAME_REQUEST_TAG);
1376
1377         if( pRenameCB == NULL)
1378         {
1379
1380             try_return( ntStatus = STATUS_INSUFFICIENT_RESOURCES);
1381         }
1382
1383         RtlZeroMemory( pRenameCB,
1384                        PAGE_SIZE);
1385
1386         pRenameCB->SourceParentId = ParentObjectInfo->FileId;
1387
1388         pRenameCB->TargetParentId = TargetParentObjectInfo->FileId;
1389
1390         pRenameCB->TargetNameLength = TargetName->Length;
1391
1392         RtlCopyMemory( pRenameCB->TargetName,
1393                        TargetName->Buffer,
1394                        TargetName->Length);
1395
1396         if( ObjectInfo->Fcb != NULL)
1397         {
1398             pAuthGroup = &ObjectInfo->Fcb->AuthGroup;
1399         }
1400
1401         //
1402         // Use the same buffer for the result control block
1403         //
1404
1405         pRenameResultCB = (AFSFileRenameResultCB *)pRenameCB;
1406
1407         ulResultLen = PAGE_SIZE;
1408
1409         ntStatus = AFSProcessRequest( AFS_REQUEST_TYPE_RENAME_FILE,
1410                                       AFS_REQUEST_FLAG_SYNCHRONOUS,
1411                                       pAuthGroup,
1412                                       &DirectoryCB->NameInformation.FileName,
1413                                       &ObjectInfo->FileId,
1414                                       pRenameCB,
1415                                       sizeof( AFSFileRenameCB) + TargetName->Length,
1416                                       pRenameResultCB,
1417                                       &ulResultLen);
1418
1419         if( ntStatus != STATUS_SUCCESS)
1420         {
1421
1422             AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
1423                           AFS_TRACE_LEVEL_ERROR,
1424                           "AFSNotifyRename failed FID %08lX-%08lX-%08lX-%08lX Status %08lX\n",
1425                           ObjectInfo->FileId.Cell,
1426                           ObjectInfo->FileId.Volume,
1427                           ObjectInfo->FileId.Vnode,
1428                           ObjectInfo->FileId.Unique,
1429                           ntStatus);
1430
1431             try_return( ntStatus);
1432         }
1433
1434         //
1435         // Update the information from the returned data
1436         //
1437
1438         ParentObjectInfo->DataVersion = pRenameResultCB->SourceParentDataVersion;
1439
1440         TargetParentObjectInfo->DataVersion = pRenameResultCB->TargetParentDataVersion;
1441
1442         //
1443         // Move over the short name
1444         //
1445
1446         DirectoryCB->NameInformation.ShortNameLength = pRenameResultCB->DirEnum.ShortNameLength;
1447
1448         if( DirectoryCB->NameInformation.ShortNameLength > 0)
1449         {
1450
1451             RtlCopyMemory( DirectoryCB->NameInformation.ShortName,
1452                            pRenameResultCB->DirEnum.ShortName,
1453                            DirectoryCB->NameInformation.ShortNameLength);
1454         }
1455
1456         if( UpdatedFID != NULL)
1457         {
1458
1459             *UpdatedFID = pRenameResultCB->DirEnum.FileId;
1460         }
1461
1462 try_exit:
1463
1464         if( pRenameCB != NULL)
1465         {
1466
1467             AFSExFreePool( pRenameCB);
1468         }
1469     }
1470
1471     return ntStatus;
1472 }
1473
1474 NTSTATUS
1475 AFSEvaluateTargetByID( IN AFSObjectInfoCB *ObjectInfo,
1476                        IN GUID *AuthGroup,
1477                        IN BOOLEAN FastCall,
1478                        OUT AFSDirEnumEntry **DirEnumEntry)
1479 {
1480
1481     NTSTATUS ntStatus = STATUS_SUCCESS;
1482     AFSEvalTargetCB stTargetID;
1483     ULONG ulResultBufferLength;
1484     AFSDirEnumEntry *pDirEnumCB = NULL;
1485     ULONG ulRequestFlags = AFS_REQUEST_FLAG_SYNCHRONOUS;
1486
1487     __Enter
1488     {
1489
1490         RtlZeroMemory( &stTargetID,
1491                        sizeof( AFSEvalTargetCB));
1492
1493         if( ObjectInfo->ParentObjectInformation != NULL)
1494         {
1495
1496             stTargetID.ParentId = ObjectInfo->ParentObjectInformation->FileId;
1497         }
1498
1499         //
1500         // Allocate our response buffer
1501         //
1502
1503         pDirEnumCB = (AFSDirEnumEntry *)AFSExAllocatePoolWithTag( PagedPool,
1504                                                                   PAGE_SIZE,
1505                                                                   AFS_GENERIC_MEMORY_2_TAG);
1506
1507         if( pDirEnumCB == NULL)
1508         {
1509
1510             try_return( ntStatus = STATUS_INSUFFICIENT_RESOURCES);
1511         }
1512
1513         //
1514         // Call to the service to evaluate the fid
1515         //
1516
1517         ulResultBufferLength = PAGE_SIZE;
1518
1519         if( FastCall)
1520         {
1521
1522             ulRequestFlags |= AFS_REQUEST_FLAG_FAST_REQUEST;
1523         }
1524
1525         ntStatus = AFSProcessRequest( AFS_REQUEST_TYPE_EVAL_TARGET_BY_ID,
1526                                       ulRequestFlags,
1527                                       AuthGroup,
1528                                       NULL,
1529                                       &ObjectInfo->FileId,
1530                                       &stTargetID,
1531                                       sizeof( AFSEvalTargetCB),
1532                                       pDirEnumCB,
1533                                       &ulResultBufferLength);
1534
1535         if( ntStatus != STATUS_SUCCESS)
1536         {
1537
1538             //
1539             // If we received back a STATUS_INVALID_HANDLE then mark the parent as requiring
1540             // verification
1541             //
1542
1543             if( ntStatus == STATUS_INVALID_HANDLE)
1544             {
1545
1546                 if( ObjectInfo->ParentObjectInformation != NULL)
1547                 {
1548
1549                     SetFlag( ObjectInfo->ParentObjectInformation->Flags, AFS_OBJECT_FLAGS_VERIFY);
1550                 }
1551             }
1552
1553             try_return( ntStatus);
1554         }
1555
1556         //
1557         // Pass back the dir enum entry
1558         //
1559
1560         if( DirEnumEntry != NULL)
1561         {
1562
1563             *DirEnumEntry = pDirEnumCB;
1564         }
1565         else
1566         {
1567
1568             AFSExFreePool( pDirEnumCB);
1569         }
1570
1571 try_exit:
1572
1573         if( !NT_SUCCESS( ntStatus))
1574         {
1575
1576             if( pDirEnumCB != NULL)
1577             {
1578
1579                 AFSExFreePool( pDirEnumCB);
1580             }
1581
1582             *DirEnumEntry = NULL;
1583         }
1584     }
1585
1586     return ntStatus;
1587 }
1588
1589 NTSTATUS
1590 AFSEvaluateTargetByName( IN GUID *AuthGroup,
1591                          IN AFSFileID *ParentFileId,
1592                          IN PUNICODE_STRING SourceName,
1593                          OUT AFSDirEnumEntry **DirEnumEntry)
1594 {
1595
1596     NTSTATUS ntStatus = STATUS_SUCCESS;
1597     AFSEvalTargetCB stTargetID;
1598     ULONG ulResultBufferLength;
1599     AFSDirEnumEntry *pDirEnumCB = NULL;
1600
1601     __Enter
1602     {
1603
1604         stTargetID.ParentId = *ParentFileId;
1605
1606         //
1607         // Allocate our response buffer
1608         //
1609
1610         pDirEnumCB = (AFSDirEnumEntry *)AFSExAllocatePoolWithTag( PagedPool,
1611                                                                   PAGE_SIZE,
1612                                                                   AFS_GENERIC_MEMORY_3_TAG);
1613
1614         if( pDirEnumCB == NULL)
1615         {
1616
1617             try_return( ntStatus = STATUS_INSUFFICIENT_RESOURCES);
1618         }
1619
1620         //
1621         // Call to the service to evaluate the fid
1622         //
1623
1624         ulResultBufferLength = PAGE_SIZE;
1625
1626         ntStatus = AFSProcessRequest( AFS_REQUEST_TYPE_EVAL_TARGET_BY_NAME,
1627                                       AFS_REQUEST_FLAG_SYNCHRONOUS,
1628                                       AuthGroup,
1629                                       SourceName,
1630                                       NULL,
1631                                       &stTargetID,
1632                                       sizeof( AFSEvalTargetCB),
1633                                       pDirEnumCB,
1634                                       &ulResultBufferLength);
1635
1636         if( ntStatus != STATUS_SUCCESS)
1637         {
1638
1639             try_return( ntStatus);
1640         }
1641
1642         //
1643         // Pass back the dir enum entry
1644         //
1645
1646         *DirEnumEntry = pDirEnumCB;
1647
1648 try_exit:
1649
1650         if( !NT_SUCCESS( ntStatus))
1651         {
1652
1653             if( pDirEnumCB != NULL)
1654             {
1655
1656                 AFSExFreePool( pDirEnumCB);
1657             }
1658
1659             *DirEnumEntry = NULL;
1660         }
1661     }
1662
1663     return ntStatus;
1664 }
1665
1666 NTSTATUS
1667 AFSRetrieveVolumeInformation( IN GUID *AuthGroup,
1668                               IN AFSFileID *FileID,
1669                               OUT AFSVolumeInfoCB *VolumeInformation)
1670 {
1671
1672     NTSTATUS ntStatus = STATUS_SUCCESS;
1673     ULONG ulResultLen = 0;
1674
1675     __Enter
1676     {
1677
1678         ulResultLen = sizeof( AFSVolumeInfoCB);
1679
1680         ntStatus = AFSProcessRequest( AFS_REQUEST_TYPE_GET_VOLUME_INFO,
1681                                       AFS_REQUEST_FLAG_SYNCHRONOUS,
1682                                       AuthGroup,
1683                                       NULL,
1684                                       FileID,
1685                                       NULL,
1686                                       0,
1687                                       VolumeInformation,
1688                                       &ulResultLen);
1689
1690         if( ntStatus != STATUS_SUCCESS)
1691         {
1692
1693             try_return( ntStatus);
1694         }
1695
1696 try_exit:
1697
1698         NOTHING;
1699     }
1700
1701     return ntStatus;
1702 }
1703
1704 NTSTATUS
1705 AFSNotifyPipeTransceive( IN AFSCcb *Ccb,
1706                          IN ULONG InputLength,
1707                          IN ULONG OutputLength,
1708                          IN void *InputDataBuffer,
1709                          OUT void *OutputDataBuffer,
1710                          OUT ULONG *BytesReturned)
1711 {
1712
1713     NTSTATUS ntStatus = STATUS_SUCCESS;
1714     ULONG ulResultLen = 0;
1715     MDL *pInputMdl = NULL, *pOutputMdl = NULL;
1716     void *pInputSystemBuffer = NULL, *pOutputSystemBuffer = NULL;
1717     ULONG ulBufferLength = OutputLength;
1718     AFSPipeIORequestCB *pIoRequest = NULL;
1719     GUID *pAuthGroup = NULL;
1720
1721     __Enter
1722     {
1723
1724         //
1725         // Map the user buffer to a system address
1726         //
1727
1728         pInputSystemBuffer = AFSLockUserBuffer( InputDataBuffer,
1729                                                 InputLength,
1730                                                 &pInputMdl);
1731
1732         if( pInputSystemBuffer == NULL)
1733         {
1734
1735             try_return( ntStatus = STATUS_INSUFFICIENT_RESOURCES);
1736         }
1737
1738         pIoRequest = (AFSPipeIORequestCB *)AFSExAllocatePoolWithTag( PagedPool,
1739                                                                      sizeof( AFSPipeIORequestCB) +
1740                                                                                 InputLength,
1741                                                                      AFS_GENERIC_MEMORY_4_TAG);
1742
1743         if( pIoRequest == NULL)
1744         {
1745
1746             try_return( ntStatus = STATUS_INSUFFICIENT_RESOURCES);
1747         }
1748
1749         RtlZeroMemory( pIoRequest,
1750                        sizeof( AFSPipeIORequestCB) + InputLength);
1751
1752         pIoRequest->RequestId = Ccb->RequestID;
1753
1754         pIoRequest->RootId = Ccb->DirectoryCB->ObjectInformation->VolumeCB->ObjectInformation.FileId;
1755
1756         pIoRequest->BufferLength = InputLength;
1757
1758         RtlCopyMemory( (void *)((char *)pIoRequest + sizeof( AFSPipeIORequestCB)),
1759                        pInputSystemBuffer,
1760                        InputLength);
1761
1762         pOutputSystemBuffer = AFSLockUserBuffer( OutputDataBuffer,
1763                                                  OutputLength,
1764                                                  &pOutputMdl);
1765
1766         if( pOutputSystemBuffer == NULL)
1767         {
1768
1769             try_return( ntStatus = STATUS_INSUFFICIENT_RESOURCES);
1770         }
1771
1772         if( Ccb->DirectoryCB->ObjectInformation->Fcb != NULL)
1773         {
1774             pAuthGroup = &Ccb->DirectoryCB->ObjectInformation->Fcb->AuthGroup;
1775         }
1776
1777         //
1778         // Send the call to the service
1779         //
1780
1781         ulResultLen = OutputLength;
1782
1783         ntStatus = AFSProcessRequest( AFS_REQUEST_TYPE_PIPE_TRANSCEIVE,
1784                                       AFS_REQUEST_FLAG_SYNCHRONOUS,
1785                                       pAuthGroup,
1786                                       &Ccb->DirectoryCB->NameInformation.FileName,
1787                                       NULL,
1788                                       pIoRequest,
1789                                       sizeof( AFSPipeIORequestCB) + InputLength,
1790                                       pOutputSystemBuffer,
1791                                       &ulResultLen);
1792
1793         if( ntStatus != STATUS_SUCCESS &&
1794             ntStatus != STATUS_BUFFER_OVERFLOW)
1795         {
1796
1797             if( NT_SUCCESS( ntStatus))
1798             {
1799
1800                 ntStatus = STATUS_DEVICE_NOT_READY;
1801             }
1802
1803             try_return( ntStatus);
1804         }
1805
1806         //
1807         // Return the bytes processed
1808         //
1809
1810         *BytesReturned = ulResultLen;
1811
1812 try_exit:
1813
1814         if( pInputMdl != NULL)
1815         {
1816
1817             MmUnlockPages( pInputMdl);
1818
1819             IoFreeMdl( pInputMdl);
1820         }
1821
1822         if( pOutputMdl != NULL)
1823         {
1824
1825             MmUnlockPages( pOutputMdl);
1826
1827             IoFreeMdl( pOutputMdl);
1828         }
1829
1830         if( pIoRequest != NULL)
1831         {
1832
1833             AFSExFreePool( pIoRequest);
1834         }
1835     }
1836
1837     return ntStatus;
1838 }
1839
1840 NTSTATUS
1841 AFSNotifySetPipeInfo( IN AFSCcb *Ccb,
1842                       IN ULONG InformationClass,
1843                       IN ULONG InputLength,
1844                       IN void *DataBuffer)
1845 {
1846
1847     NTSTATUS ntStatus = STATUS_SUCCESS;
1848     AFSPipeInfoRequestCB *pInfoRequest = NULL;
1849     GUID *pAuthGroup = NULL;
1850
1851     __Enter
1852     {
1853
1854         pInfoRequest = (AFSPipeInfoRequestCB *)AFSExAllocatePoolWithTag( PagedPool,
1855                                                                          sizeof( AFSPipeInfoRequestCB) +
1856                                                                                 InputLength,
1857                                                                          AFS_GENERIC_MEMORY_5_TAG);
1858
1859         if( pInfoRequest == NULL)
1860         {
1861
1862             try_return( ntStatus = STATUS_INSUFFICIENT_RESOURCES);
1863         }
1864
1865         RtlZeroMemory( pInfoRequest,
1866                        sizeof( AFSPipeInfoRequestCB) + InputLength);
1867
1868         pInfoRequest->RequestId = Ccb->RequestID;
1869
1870         pInfoRequest->RootId = Ccb->DirectoryCB->ObjectInformation->VolumeCB->ObjectInformation.FileId;
1871
1872         pInfoRequest->BufferLength = InputLength;
1873
1874         pInfoRequest->InformationClass = InformationClass;
1875
1876         RtlCopyMemory( (void *)((char *)pInfoRequest + sizeof( AFSPipeInfoRequestCB)),
1877                        DataBuffer,
1878                        InputLength);
1879
1880         if( Ccb->DirectoryCB->ObjectInformation->Fcb != NULL)
1881         {
1882             pAuthGroup = &Ccb->DirectoryCB->ObjectInformation->Fcb->AuthGroup;
1883         }
1884
1885         //
1886         // Send the call to the service
1887         //
1888
1889         ntStatus = AFSProcessRequest( AFS_REQUEST_TYPE_PIPE_SET_INFO,
1890                                       AFS_REQUEST_FLAG_SYNCHRONOUS,
1891                                       pAuthGroup,
1892                                       &Ccb->DirectoryCB->NameInformation.FileName,
1893                                       NULL,
1894                                       pInfoRequest,
1895                                       sizeof( AFSPipeInfoRequestCB) + InputLength,
1896                                       NULL,
1897                                       NULL);
1898
1899         if( ntStatus != STATUS_SUCCESS)
1900         {
1901
1902             if( NT_SUCCESS( ntStatus))
1903             {
1904
1905                 ntStatus = STATUS_DEVICE_NOT_READY;
1906             }
1907
1908             try_return( ntStatus);
1909         }
1910
1911 try_exit:
1912
1913         if( pInfoRequest != NULL)
1914         {
1915
1916             AFSExFreePool( pInfoRequest);
1917         }
1918     }
1919
1920     return ntStatus;
1921 }
1922
1923 NTSTATUS
1924 AFSNotifyQueryPipeInfo( IN AFSCcb *Ccb,
1925                         IN ULONG InformationClass,
1926                         IN ULONG OutputLength,
1927                         IN void *DataBuffer,
1928                         OUT ULONG *BytesReturned)
1929 {
1930
1931     NTSTATUS ntStatus = STATUS_SUCCESS;
1932     AFSPipeInfoRequestCB stInfoRequest;
1933     ULONG ulBytesProcessed = 0;
1934     GUID *pAuthGroup = NULL;
1935
1936     __Enter
1937     {
1938
1939         RtlZeroMemory( &stInfoRequest,
1940                        sizeof( AFSPipeInfoRequestCB));
1941
1942         stInfoRequest.RequestId = Ccb->RequestID;
1943
1944         stInfoRequest.RootId = Ccb->DirectoryCB->ObjectInformation->VolumeCB->ObjectInformation.FileId;
1945
1946         stInfoRequest.BufferLength = OutputLength;
1947
1948         stInfoRequest.InformationClass = InformationClass;
1949
1950         ulBytesProcessed = OutputLength;
1951
1952         if( Ccb->DirectoryCB->ObjectInformation->Fcb != NULL)
1953         {
1954             pAuthGroup = &Ccb->DirectoryCB->ObjectInformation->Fcb->AuthGroup;
1955         }
1956
1957         //
1958         // Send the call to the service
1959         //
1960
1961         ntStatus = AFSProcessRequest( AFS_REQUEST_TYPE_PIPE_QUERY_INFO,
1962                                       AFS_REQUEST_FLAG_SYNCHRONOUS,
1963                                       pAuthGroup,
1964                                       &Ccb->DirectoryCB->NameInformation.FileName,
1965                                       NULL,
1966                                       &stInfoRequest,
1967                                       sizeof( AFSPipeInfoRequestCB),
1968                                       DataBuffer,
1969                                       &ulBytesProcessed);
1970
1971         if( ntStatus != STATUS_SUCCESS)
1972         {
1973
1974             if( NT_SUCCESS( ntStatus))
1975             {
1976
1977                 ntStatus = STATUS_DEVICE_NOT_READY;
1978             }
1979
1980             try_return( ntStatus);
1981         }
1982
1983         *BytesReturned = ulBytesProcessed;
1984
1985 try_exit:
1986
1987         NOTHING;
1988     }
1989
1990     return ntStatus;
1991 }
1992
1993 NTSTATUS
1994 AFSReleaseFid( IN AFSFileID *FileId)
1995 {
1996
1997     NTSTATUS ntStatus = STATUS_SUCCESS;
1998
1999     __Enter
2000     {
2001
2002         ntStatus = AFSProcessRequest( AFS_REQUEST_TYPE_RELEASE_FID,
2003                                       0,
2004                                       NULL,
2005                                       NULL,
2006                                       FileId,
2007                                       NULL,
2008                                       0,
2009                                       NULL,
2010                                       NULL);
2011     }
2012
2013     return ntStatus;
2014 }
2015
2016 BOOLEAN
2017 AFSIsExtentRequestQueued( IN AFSFileID *FileID,
2018                           IN LARGE_INTEGER *ExtentOffset,
2019                           IN ULONG Length)
2020 {
2021
2022     BOOLEAN bRequestQueued = FALSE;
2023     NTSTATUS ntStatus = STATUS_SUCCESS;
2024     AFSDeviceExt    *pControlDevExt = (AFSDeviceExt *)AFSControlDeviceObject->DeviceExtension;
2025     AFSCommSrvcCB   *pCommSrvc = NULL;
2026     AFSPoolEntry    *pPoolEntry = NULL;
2027     AFSRequestExtentsCB *pRequestExtents = NULL;
2028
2029     __Enter
2030     {
2031
2032
2033         pCommSrvc = &pControlDevExt->Specific.Control.CommServiceCB;
2034
2035         AFSAcquireShared( &pCommSrvc->IrpPoolLock,
2036                           TRUE);
2037
2038         pPoolEntry = pCommSrvc->RequestPoolHead;
2039
2040         while( pPoolEntry != NULL)
2041         {
2042
2043             if( pPoolEntry->RequestType == AFS_REQUEST_TYPE_REQUEST_FILE_EXTENTS)
2044             {
2045
2046                 if( AFSIsEqualFID( &pPoolEntry->FileId, FileID))
2047                 {
2048
2049                     pRequestExtents = (AFSRequestExtentsCB *)pPoolEntry->Data;
2050
2051                     if( pRequestExtents->ByteOffset.QuadPart == ExtentOffset->QuadPart &&
2052                         pRequestExtents->Length == Length)
2053                     {
2054
2055                         bRequestQueued = TRUE;
2056                     }
2057                 }
2058             }
2059
2060             pPoolEntry = pPoolEntry->fLink;
2061         }
2062
2063         AFSReleaseResource( &pCommSrvc->IrpPoolLock);
2064     }
2065
2066     return bRequestQueued;
2067 }