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