Windows: fix deadlock in symlink Attrib retrieval
[openafs.git] / src / WINNT / afsrdr / kernel / lib / AFSFileInfo.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: AFSFileInfo.cpp
37 //
38
39 #include "AFSCommon.h"
40
41 //
42 // Function: AFSQueryFileInfo
43 //
44 // Description:
45 //
46 //      This function is the dispatch handler for the IRP_MJ_QUERY_FILE_INFORMATION request
47 //
48 // Return:
49 //
50 //      A status is returned for the function
51 //
52
53 NTSTATUS
54 AFSQueryFileInfo( IN PDEVICE_OBJECT LibDeviceObject,
55                   IN PIRP Irp)
56 {
57
58     NTSTATUS ntStatus = STATUS_SUCCESS;
59     AFSDeviceExt *pDeviceExt = (AFSDeviceExt *)AFSRDRDeviceObject->DeviceExtension;
60     ULONG ulRequestType = 0;
61     IO_STACK_LOCATION *pIrpSp = IoGetCurrentIrpStackLocation( Irp);
62     AFSFcb *pFcb = NULL;
63     AFSCcb *pCcb = NULL;
64     PFILE_OBJECT pFileObject;
65     BOOLEAN bReleaseMain = FALSE;
66     LONG lLength;
67     FILE_INFORMATION_CLASS stFileInformationClass;
68     PVOID pBuffer;
69
70     __try
71     {
72
73         //
74         // Determine the type of request this request is
75         //
76
77         pFcb = (AFSFcb *)pIrpSp->FileObject->FsContext;
78
79         pCcb = (AFSCcb *)pIrpSp->FileObject->FsContext2;
80
81         if( pFcb == NULL)
82         {
83
84             AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
85                           AFS_TRACE_LEVEL_ERROR,
86                           "AFSQueryFileInfo Attempted access (%08lX) when pFcb == NULL\n",
87                           Irp);
88
89             try_return( ntStatus = STATUS_INVALID_DEVICE_REQUEST);
90         }
91
92         lLength = (LONG)pIrpSp->Parameters.QueryFile.Length;
93         stFileInformationClass = pIrpSp->Parameters.QueryFile.FileInformationClass;
94         pBuffer = Irp->AssociatedIrp.SystemBuffer;
95
96         //
97         // Grab the main shared right off the bat
98         //
99
100         AFSDbgLogMsg( AFS_SUBSYSTEM_LOCK_PROCESSING,
101                       AFS_TRACE_LEVEL_VERBOSE,
102                       "AFSQueryFileInfo Acquiring Fcb lock %08lX SHARED %08lX\n",
103                       &pFcb->NPFcb->Resource,
104                       PsGetCurrentThread());
105
106         AFSAcquireShared( &pFcb->NPFcb->Resource,
107                           TRUE);
108
109         bReleaseMain = TRUE;
110
111         //
112         // Don't allow requests against IOCtl nodes
113         //
114
115         if( pFcb->Header.NodeTypeCode == AFS_SPECIAL_SHARE_FCB)
116         {
117
118             AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
119                           AFS_TRACE_LEVEL_VERBOSE,
120                           "AFSQueryFileInfo Processing request against SpecialShare Fcb\n");
121
122             ntStatus = AFSProcessShareQueryInfo( Irp,
123                                                  pFcb,
124                                                  pCcb);
125
126             try_return( ntStatus);
127         }
128         else if( pFcb->Header.NodeTypeCode == AFS_IOCTL_FCB)
129         {
130             AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
131                           AFS_TRACE_LEVEL_VERBOSE,
132                           "AFSQueryFileInfo request against PIOCtl Fcb\n");
133
134             ntStatus = AFSProcessPIOCtlQueryInfo( Irp,
135                                                   pFcb,
136                                                   pCcb,
137                                                   &lLength);
138
139             try_return( ntStatus);
140         }
141
142         //
143         // Process the request
144         //
145
146         switch( stFileInformationClass)
147         {
148
149             case FileAllInformation:
150             {
151
152                 PFILE_ALL_INFORMATION pAllInfo;
153
154                 //
155                 //  For the all information class we'll typecast a local
156                 //  pointer to the output buffer and then call the
157                 //  individual routines to fill in the buffer.
158                 //
159
160                 pAllInfo = (PFILE_ALL_INFORMATION)pBuffer;
161
162                 ntStatus = AFSQueryBasicInfo( Irp,
163                                               pCcb->DirectoryCB,
164                                               &pAllInfo->BasicInformation,
165                                               &lLength);
166
167                 if( !NT_SUCCESS( ntStatus))
168                 {
169
170                     try_return( ntStatus);
171                 }
172
173                 ntStatus = AFSQueryStandardInfo( Irp,
174                                                  pCcb->DirectoryCB,
175                                                  &pAllInfo->StandardInformation,
176                                                  &lLength);
177
178                 if( !NT_SUCCESS( ntStatus))
179                 {
180
181                     try_return( ntStatus);
182                 }
183
184                 ntStatus = AFSQueryInternalInfo( Irp,
185                                                  pFcb,
186                                                  &pAllInfo->InternalInformation,
187                                                  &lLength);
188
189                 if( !NT_SUCCESS( ntStatus))
190                 {
191
192                     try_return( ntStatus);
193                 }
194
195                 ntStatus = AFSQueryEaInfo( Irp,
196                                            pCcb->DirectoryCB,
197                                            &pAllInfo->EaInformation,
198                                            &lLength);
199
200                 if( !NT_SUCCESS( ntStatus))
201                 {
202
203                     try_return( ntStatus);
204                 }
205
206                 ntStatus = AFSQueryAccess( Irp,
207                                            pFcb,
208                                            &pAllInfo->AccessInformation,
209                                            &lLength);
210
211                 if( !NT_SUCCESS( ntStatus))
212                 {
213
214                     try_return( ntStatus);
215                 }
216
217                 ntStatus = AFSQueryPositionInfo( Irp,
218                                                  pFcb,
219                                                  &pAllInfo->PositionInformation,
220                                                  &lLength);
221
222                 if( !NT_SUCCESS( ntStatus))
223                 {
224
225                     try_return( ntStatus);
226                 }
227
228                 ntStatus = AFSQueryMode( Irp,
229                                          pFcb,
230                                          &pAllInfo->ModeInformation,
231                                          &lLength);
232
233                 if( !NT_SUCCESS( ntStatus))
234                 {
235
236                     try_return( ntStatus);
237                 }
238
239                 ntStatus = AFSQueryAlignment( Irp,
240                                               pFcb,
241                                               &pAllInfo->AlignmentInformation,
242                                               &lLength);
243
244                 if( !NT_SUCCESS( ntStatus))
245                 {
246
247                     try_return( ntStatus);
248                 }
249
250                 ntStatus = AFSQueryNameInfo( Irp,
251                                              pCcb->DirectoryCB,
252                                              &pAllInfo->NameInformation,
253                                              &lLength);
254
255                 if( !NT_SUCCESS( ntStatus))
256                 {
257
258                     try_return( ntStatus);
259                 }
260
261                 break;
262             }
263
264             case FileBasicInformation:
265             {
266
267                 ntStatus = AFSQueryBasicInfo( Irp,
268                                               pCcb->DirectoryCB,
269                                               (PFILE_BASIC_INFORMATION)pBuffer,
270                                               &lLength);
271
272                 break;
273             }
274
275             case FileStandardInformation:
276             {
277
278                 ntStatus = AFSQueryStandardInfo( Irp,
279                                                  pCcb->DirectoryCB,
280                                                  (PFILE_STANDARD_INFORMATION)pBuffer,
281                                                  &lLength);
282
283                 break;
284             }
285
286             case FileInternalInformation:
287             {
288
289                 ntStatus = AFSQueryInternalInfo( Irp,
290                                                  pFcb,
291                                                  (PFILE_INTERNAL_INFORMATION)pBuffer,
292                                                  &lLength);
293
294                 break;
295             }
296
297             case FileEaInformation:
298             {
299
300                 ntStatus = AFSQueryEaInfo( Irp,
301                                            pCcb->DirectoryCB,
302                                            (PFILE_EA_INFORMATION)pBuffer,
303                                            &lLength);
304
305                 break;
306             }
307
308             case FilePositionInformation:
309             {
310
311                 ntStatus = AFSQueryPositionInfo( Irp,
312                                       pFcb,
313                                       (PFILE_POSITION_INFORMATION)pBuffer,
314                                       &lLength);
315
316                 break;
317             }
318
319             case FileNameInformation:
320             {
321
322                 ntStatus = AFSQueryNameInfo( Irp,
323                                   pCcb->DirectoryCB,
324                                   (PFILE_NAME_INFORMATION)pBuffer,
325                                   &lLength);
326
327                 break;
328             }
329
330             case FileAlternateNameInformation:
331             {
332
333                 ntStatus = AFSQueryShortNameInfo( Irp,
334                                        pCcb->DirectoryCB,
335                                        (PFILE_NAME_INFORMATION)pBuffer,
336                                        &lLength);
337
338                 break;
339             }
340
341             case FileNetworkOpenInformation:
342             {
343
344                 ntStatus = AFSQueryNetworkInfo( Irp,
345                                      pCcb->DirectoryCB,
346                                      (PFILE_NETWORK_OPEN_INFORMATION)pBuffer,
347                                      &lLength);
348
349                 break;
350             }
351
352             case FileStreamInformation:
353             {
354
355                 ntStatus = AFSQueryStreamInfo( Irp,
356                                                pCcb->DirectoryCB,
357                                                (FILE_STREAM_INFORMATION *)pBuffer,
358                                                &lLength);
359
360                 break;
361             }
362
363
364             case FileAttributeTagInformation:
365             {
366
367                 ntStatus = AFSQueryAttribTagInfo( Irp,
368                                                   pCcb->DirectoryCB,
369                                                   (FILE_ATTRIBUTE_TAG_INFORMATION *)pBuffer,
370                                                   &lLength);
371
372                 break;
373             }
374
375             case FileRemoteProtocolInformation:
376             {
377
378                     ntStatus = AFSQueryRemoteProtocolInfo( Irp,
379                                                            pCcb->DirectoryCB,
380                                                            (FILE_REMOTE_PROTOCOL_INFORMATION *)pBuffer,
381                                                            &lLength);
382
383                 break;
384             }
385
386         default:
387
388                 ntStatus = STATUS_INVALID_PARAMETER;
389
390                 break;
391         }
392
393 try_exit:
394
395         Irp->IoStatus.Information = pIrpSp->Parameters.QueryFile.Length - lLength;
396
397         if( bReleaseMain)
398         {
399
400             AFSReleaseResource( &pFcb->NPFcb->Resource);
401         }
402
403         if( !NT_SUCCESS( ntStatus) &&
404             ntStatus != STATUS_INVALID_PARAMETER &&
405             ntStatus != STATUS_BUFFER_OVERFLOW)
406         {
407
408             if( pCcb != NULL &&
409                 pCcb->DirectoryCB != NULL)
410             {
411
412                 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
413                               AFS_TRACE_LEVEL_ERROR,
414                               "AFSQueryFileInfo Failed to process request for %wZ FID %08lX-%08lX-%08lX-%08lX Status %08lX\n",
415                               &pCcb->DirectoryCB->NameInformation.FileName,
416                               pCcb->DirectoryCB->ObjectInformation->FileId.Cell,
417                               pCcb->DirectoryCB->ObjectInformation->FileId.Volume,
418                               pCcb->DirectoryCB->ObjectInformation->FileId.Vnode,
419                               pCcb->DirectoryCB->ObjectInformation->FileId.Unique,
420                               ntStatus);
421             }
422         }
423     }
424     __except( AFSExceptionFilter( GetExceptionCode(), GetExceptionInformation()) )
425     {
426
427         AFSDbgLogMsg( 0,
428                       0,
429                       "EXCEPTION - AFSQueryFileInfo\n");
430
431         ntStatus = STATUS_UNSUCCESSFUL;
432
433         if( bReleaseMain)
434         {
435
436             AFSReleaseResource( &pFcb->NPFcb->Resource);
437         }
438     }
439
440     AFSCompleteRequest( Irp,
441                         ntStatus);
442
443     return ntStatus;
444 }
445
446 //
447 // Function: AFSSetFileInfo
448 //
449 // Description:
450 //
451 //      This function is the dispatch handler for the IRP_MJ_SET_FILE_INFORMATION request
452 //
453 // Return:
454 //
455 //      A status is returned for the function
456 //
457
458 NTSTATUS
459 AFSSetFileInfo( IN PDEVICE_OBJECT LibDeviceObject,
460                 IN PIRP Irp)
461 {
462
463     NTSTATUS ntStatus = STATUS_SUCCESS;
464     AFSDeviceExt *pDeviceExt = (AFSDeviceExt *)AFSRDRDeviceObject->DeviceExtension;
465     IO_STACK_LOCATION *pIrpSp = IoGetCurrentIrpStackLocation( Irp);
466     AFSFcb *pFcb = NULL;
467     AFSCcb *pCcb = NULL;
468     BOOLEAN bCompleteRequest = TRUE;
469     FILE_INFORMATION_CLASS FileInformationClass;
470     BOOLEAN bCanQueueRequest = FALSE;
471     PFILE_OBJECT pFileObject = NULL;
472     BOOLEAN bReleaseMain = FALSE;
473     BOOLEAN bUpdateFileInfo = FALSE;
474     AFSFileID stParentFileId;
475
476     __try
477     {
478
479         pFileObject = pIrpSp->FileObject;
480
481         pFcb = (AFSFcb *)pFileObject->FsContext;
482         pCcb = (AFSCcb *)pFileObject->FsContext2;
483
484         if( pFcb == NULL)
485         {
486
487             AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
488                           AFS_TRACE_LEVEL_ERROR,
489                           "AFSSetFileInfo Attempted access (%08lX) when pFcb == NULL\n",
490                           Irp);
491
492             try_return( ntStatus = STATUS_INVALID_DEVICE_REQUEST);
493         }
494
495         bCanQueueRequest = !(IoIsOperationSynchronous( Irp) | (KeGetCurrentIrql() != PASSIVE_LEVEL));
496         FileInformationClass = pIrpSp->Parameters.SetFile.FileInformationClass;
497
498         //
499         // Grab the Fcb EXCL
500         //
501
502         AFSDbgLogMsg( AFS_SUBSYSTEM_LOCK_PROCESSING,
503                       AFS_TRACE_LEVEL_VERBOSE,
504                       "AFSSetFileInfo Acquiring Fcb lock %08lX EXCL %08lX\n",
505                       &pFcb->NPFcb->Resource,
506                       PsGetCurrentThread());
507
508         AFSAcquireExcl( &pFcb->NPFcb->Resource,
509                         TRUE);
510
511         bReleaseMain = TRUE;
512
513         //
514         // Don't allow requests against IOCtl nodes
515         //
516
517         if( pFcb->Header.NodeTypeCode == AFS_IOCTL_FCB)
518         {
519
520             AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
521                           AFS_TRACE_LEVEL_ERROR,
522                           "AFSSetFileInfo Failing request against PIOCtl Fcb\n");
523
524             try_return( ntStatus = STATUS_INVALID_DEVICE_REQUEST);
525         }
526         else if( pFcb->Header.NodeTypeCode == AFS_SPECIAL_SHARE_FCB)
527         {
528
529             AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
530                           AFS_TRACE_LEVEL_VERBOSE,
531                           "AFSSetFileInfo Processing request against SpecialShare Fcb\n");
532
533             ntStatus = AFSProcessShareSetInfo( Irp,
534                                                pFcb,
535                                                pCcb);
536
537             try_return( ntStatus);
538         }
539
540         if( BooleanFlagOn( pFcb->ObjectInformation->VolumeCB->VolumeInformation.Characteristics, FILE_READ_ONLY_DEVICE))
541         {
542
543             AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
544                           AFS_TRACE_LEVEL_ERROR,
545                           "AFSSetFileInfo Request failed due to read only volume\n",
546                           Irp);
547
548             try_return( ntStatus = STATUS_ACCESS_DENIED);
549         }
550
551         //
552         // Ensure rename operations are synchronous
553         //
554
555         if( FileInformationClass == FileRenameInformation)
556         {
557
558             bCanQueueRequest = FALSE;
559         }
560
561         //
562         // Store away the parent fid
563         //
564
565         RtlZeroMemory( &stParentFileId,
566                        sizeof( AFSFileID));
567
568         if( pFcb->ObjectInformation->ParentObjectInformation != NULL)
569         {
570             stParentFileId = pFcb->ObjectInformation->ParentObjectInformation->FileId;
571         }
572
573         //
574         // Process the request
575         //
576
577         switch( FileInformationClass)
578         {
579
580             case FileBasicInformation:
581             {
582
583                 bUpdateFileInfo = TRUE;
584
585                 ntStatus = AFSSetBasicInfo( Irp,
586                                             pCcb->DirectoryCB);
587
588                 break;
589             }
590
591             case FileDispositionInformation:
592             {
593
594                 ntStatus = AFSSetDispositionInfo( Irp,
595                                                   pCcb->DirectoryCB);
596
597                 break;
598             }
599
600             case FileRenameInformation:
601             {
602
603                 ntStatus = AFSSetRenameInfo( Irp);
604
605                 break;
606             }
607
608             case FilePositionInformation:
609             {
610
611                 ntStatus = AFSSetPositionInfo( Irp,
612                                                pCcb->DirectoryCB);
613
614                 break;
615             }
616
617             case FileLinkInformation:
618             {
619
620                 ntStatus = STATUS_INVALID_DEVICE_REQUEST;
621
622                 break;
623             }
624
625             case FileAllocationInformation:
626             {
627
628                 ntStatus = AFSSetAllocationInfo( Irp,
629                                                  pCcb->DirectoryCB);
630
631                 break;
632             }
633
634             case FileEndOfFileInformation:
635             {
636
637                 ntStatus = AFSSetEndOfFileInfo( Irp,
638                                                 pCcb->DirectoryCB);
639
640                 break;
641             }
642
643             default:
644
645                 ntStatus = STATUS_INVALID_PARAMETER;
646
647                 break;
648         }
649
650 try_exit:
651
652         if( bReleaseMain)
653         {
654
655             AFSReleaseResource( &pFcb->NPFcb->Resource);
656         }
657
658         if( NT_SUCCESS( ntStatus) &&
659             bUpdateFileInfo)
660         {
661
662             ntStatus = AFSUpdateFileInformation( &stParentFileId,
663                                                  pFcb->ObjectInformation,
664                                                  &pFcb->AuthGroup);
665
666             if( !NT_SUCCESS( ntStatus))
667             {
668
669                 AFSAcquireExcl( &pFcb->NPFcb->Resource,
670                                 TRUE);
671
672                 //
673                 // Unwind the update and fail the request
674                 //
675
676                 AFSUnwindFileInfo( pFcb,
677                                    pCcb);
678
679                 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
680                               AFS_TRACE_LEVEL_ERROR,
681                               "AFSSetFileInfo Failed to send file info update to service request for %wZ FID %08lX-%08lX-%08lX-%08lX Status %08lX\n",
682                               &pCcb->DirectoryCB->NameInformation.FileName,
683                               pCcb->DirectoryCB->ObjectInformation->FileId.Cell,
684                               pCcb->DirectoryCB->ObjectInformation->FileId.Volume,
685                               pCcb->DirectoryCB->ObjectInformation->FileId.Vnode,
686                               pCcb->DirectoryCB->ObjectInformation->FileId.Unique,
687                               ntStatus);
688
689                 AFSReleaseResource( &pFcb->NPFcb->Resource);
690             }
691         }
692
693         if( !NT_SUCCESS( ntStatus))
694         {
695
696             if( pCcb != NULL &&
697                 pCcb->DirectoryCB != NULL)
698             {
699
700                 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
701                               AFS_TRACE_LEVEL_ERROR,
702                               "AFSSetFileInfo Failed to process request for %wZ FID %08lX-%08lX-%08lX-%08lX Status %08lX\n",
703                               &pCcb->DirectoryCB->NameInformation.FileName,
704                               pCcb->DirectoryCB->ObjectInformation->FileId.Cell,
705                               pCcb->DirectoryCB->ObjectInformation->FileId.Volume,
706                               pCcb->DirectoryCB->ObjectInformation->FileId.Vnode,
707                               pCcb->DirectoryCB->ObjectInformation->FileId.Unique,
708                               ntStatus);
709             }
710         }
711     }
712     __except( AFSExceptionFilter( GetExceptionCode(), GetExceptionInformation()) )
713     {
714
715         AFSDbgLogMsg( 0,
716                       0,
717                       "EXCEPTION - AFSSetFileInfo\n");
718
719         ntStatus = STATUS_UNSUCCESSFUL;
720     }
721
722     AFSCompleteRequest( Irp,
723                         ntStatus);
724
725     return ntStatus;
726 }
727
728 //
729 // Function: AFSQueryBasicInfo
730 //
731 // Description:
732 //
733 //      This function is the handler for the query basic information request
734 //
735 // Return:
736 //
737 //      A status is returned for the function
738 //
739
740 NTSTATUS
741 AFSQueryBasicInfo( IN PIRP Irp,
742                    IN AFSDirectoryCB *DirectoryCB,
743                    IN OUT PFILE_BASIC_INFORMATION Buffer,
744                    IN OUT PLONG Length)
745 {
746     NTSTATUS ntStatus = STATUS_SUCCESS;
747     AFSDeviceExt *pDeviceExt = (AFSDeviceExt *)AFSRDRDeviceObject->DeviceExtension;
748     ULONG ulFileAttribs = 0;
749     AFSFcb *pFcb = NULL;
750     AFSCcb *pCcb = NULL;
751     IO_STACK_LOCATION *pIrpSp = IoGetCurrentIrpStackLocation( Irp);
752     AFSFileInfoCB stFileInfo;
753     AFSDirectoryCB *pParentDirectoryCB = NULL;
754     UNICODE_STRING uniParentPath;
755
756     if( *Length >= sizeof( FILE_BASIC_INFORMATION))
757     {
758
759         RtlZeroMemory( Buffer,
760                        *Length);
761
762         ulFileAttribs = DirectoryCB->ObjectInformation->FileAttributes;
763
764         pFcb = (AFSFcb *)pIrpSp->FileObject->FsContext;
765         pCcb = (AFSCcb *)pIrpSp->FileObject->FsContext2;
766
767         if( DirectoryCB->ObjectInformation->FileType == AFS_FILE_TYPE_SYMLINK)
768         {
769
770             pParentDirectoryCB = AFSGetParentEntry( pCcb->NameArray);
771
772             AFSRetrieveParentPath( &pCcb->FullFileName,
773                                    &uniParentPath);
774
775             RtlZeroMemory( &stFileInfo,
776                            sizeof( AFSFileInfoCB));
777
778             //
779             // Can't hold the Fcb while evaluating the path, leads to lock inversion
780             //
781
782             AFSReleaseResource( &pFcb->NPFcb->Resource);
783
784             if( NT_SUCCESS( AFSRetrieveFileAttributes( pParentDirectoryCB,
785                                                        DirectoryCB,
786                                                        &uniParentPath,
787                                                        NULL,
788                                                        &stFileInfo)))
789             {
790                 ulFileAttribs = stFileInfo.FileAttributes;
791
792                 ulFileAttribs |= FILE_ATTRIBUTE_REPARSE_POINT;
793             }
794
795             AFSAcquireShared( &pFcb->NPFcb->Resource,
796                               TRUE);
797         }
798
799         Buffer->CreationTime = DirectoryCB->ObjectInformation->CreationTime;
800         Buffer->LastAccessTime = DirectoryCB->ObjectInformation->LastAccessTime;
801         Buffer->LastWriteTime = DirectoryCB->ObjectInformation->LastWriteTime;
802         Buffer->ChangeTime = DirectoryCB->ObjectInformation->ChangeTime;
803         Buffer->FileAttributes = ulFileAttribs;
804
805         if( DirectoryCB->NameInformation.FileName.Buffer[ 0] == L'.' &&
806             BooleanFlagOn( pDeviceExt->DeviceFlags, AFS_DEVICE_FLAG_HIDE_DOT_NAMES))
807         {
808
809             if ( Buffer->FileAttributes != FILE_ATTRIBUTE_NORMAL)
810             {
811                 Buffer->FileAttributes |= FILE_ATTRIBUTE_HIDDEN;
812             }
813             else
814             {
815                 Buffer->FileAttributes = FILE_ATTRIBUTE_HIDDEN;
816             }
817         }
818
819         *Length -= sizeof( FILE_BASIC_INFORMATION);
820     }
821     else
822     {
823
824         ntStatus = STATUS_BUFFER_TOO_SMALL;
825     }
826
827     return ntStatus;
828 }
829
830 NTSTATUS
831 AFSQueryStandardInfo( IN PIRP Irp,
832                       IN AFSDirectoryCB *DirectoryCB,
833                       IN OUT PFILE_STANDARD_INFORMATION Buffer,
834                       IN OUT PLONG Length)
835 {
836
837     NTSTATUS ntStatus = STATUS_SUCCESS;
838     AFSFcb *pFcb = NULL;
839     AFSCcb *pCcb = NULL;
840     PIO_STACK_LOCATION pIrpSp = IoGetCurrentIrpStackLocation( Irp);
841     AFSFileInfoCB stFileInfo;
842     AFSDirectoryCB *pParentDirectoryCB = NULL;
843     UNICODE_STRING uniParentPath;
844     ULONG ulFileAttribs = 0;
845
846     if( *Length >= sizeof( FILE_STANDARD_INFORMATION))
847     {
848
849         pFcb = (AFSFcb *)pIrpSp->FileObject->FsContext;
850         pCcb = (AFSCcb *)pIrpSp->FileObject->FsContext2;
851
852         RtlZeroMemory( Buffer,
853                        *Length);
854
855         Buffer->NumberOfLinks = 1;
856         Buffer->DeletePending = BooleanFlagOn( pCcb->DirectoryCB->Flags, AFS_DIR_ENTRY_PENDING_DELETE);
857
858         Buffer->AllocationSize.QuadPart = (ULONGLONG)((DirectoryCB->ObjectInformation->AllocationSize.QuadPart/PAGE_SIZE) + 1) * PAGE_SIZE;
859
860         Buffer->EndOfFile = DirectoryCB->ObjectInformation->EndOfFile;
861
862         ulFileAttribs = DirectoryCB->ObjectInformation->FileAttributes;
863
864         if( DirectoryCB->ObjectInformation->FileType == AFS_FILE_TYPE_SYMLINK)
865         {
866
867             pParentDirectoryCB = AFSGetParentEntry( pCcb->NameArray);
868
869             AFSRetrieveParentPath( &pCcb->FullFileName,
870                                    &uniParentPath);
871
872             RtlZeroMemory( &stFileInfo,
873                            sizeof( AFSFileInfoCB));
874
875             //
876             // Can't hold the Fcb while evaluating the path, leads to lock inversion
877             //
878
879             AFSReleaseResource( &pFcb->NPFcb->Resource);
880
881             if( NT_SUCCESS( AFSRetrieveFileAttributes( pParentDirectoryCB,
882                                                        DirectoryCB,
883                                                        &uniParentPath,
884                                                        NULL,
885                                                        &stFileInfo)))
886             {
887                 ulFileAttribs = stFileInfo.FileAttributes;
888             }
889
890             AFSAcquireShared( &pFcb->NPFcb->Resource,
891                               TRUE);
892         }
893
894         Buffer->Directory = BooleanFlagOn( ulFileAttribs, FILE_ATTRIBUTE_DIRECTORY);
895
896         *Length -= sizeof( FILE_STANDARD_INFORMATION);
897     }
898     else
899     {
900
901         ntStatus = STATUS_BUFFER_TOO_SMALL;
902     }
903
904     return ntStatus;
905 }
906
907 NTSTATUS
908 AFSQueryInternalInfo( IN PIRP Irp,
909                       IN AFSFcb *Fcb,
910                       IN OUT PFILE_INTERNAL_INFORMATION Buffer,
911                       IN OUT PLONG Length)
912 {
913
914     NTSTATUS ntStatus = STATUS_SUCCESS;
915
916     if( *Length >= sizeof( FILE_INTERNAL_INFORMATION))
917     {
918
919         Buffer->IndexNumber.HighPart = Fcb->ObjectInformation->FileId.Volume;
920
921         Buffer->IndexNumber.LowPart = Fcb->ObjectInformation->FileId.Vnode;
922
923         *Length -= sizeof( FILE_INTERNAL_INFORMATION);
924     }
925     else
926     {
927
928         ntStatus = STATUS_BUFFER_TOO_SMALL;
929     }
930
931     return ntStatus;
932 }
933
934 NTSTATUS
935 AFSQueryEaInfo( IN PIRP Irp,
936                 IN AFSDirectoryCB *DirectoryCB,
937                 IN OUT PFILE_EA_INFORMATION Buffer,
938                 IN OUT PLONG Length)
939 {
940
941     NTSTATUS ntStatus = STATUS_SUCCESS;
942
943     RtlZeroMemory( Buffer,
944                    *Length);
945
946     if( *Length >= sizeof( FILE_EA_INFORMATION))
947     {
948
949         Buffer->EaSize = 0;
950
951         *Length -= sizeof( FILE_EA_INFORMATION);
952     }
953     else
954     {
955
956         ntStatus = STATUS_BUFFER_TOO_SMALL;
957     }
958
959     return ntStatus;
960 }
961
962 NTSTATUS
963 AFSQueryPositionInfo( IN PIRP Irp,
964                       IN AFSFcb *Fcb,
965                       IN OUT PFILE_POSITION_INFORMATION Buffer,
966                       IN OUT PLONG Length)
967 {
968
969     NTSTATUS ntStatus = STATUS_SUCCESS;
970     PIO_STACK_LOCATION pIrpSp = IoGetCurrentIrpStackLocation( Irp);
971
972     if( *Length >= sizeof( FILE_POSITION_INFORMATION))
973     {
974
975         RtlZeroMemory( Buffer,
976                        *Length);
977
978         Buffer->CurrentByteOffset.QuadPart = pIrpSp->FileObject->CurrentByteOffset.QuadPart;
979
980         *Length -= sizeof( FILE_POSITION_INFORMATION);
981     }
982     else
983     {
984
985         ntStatus = STATUS_BUFFER_TOO_SMALL;
986     }
987
988     return ntStatus;
989 }
990
991 NTSTATUS
992 AFSQueryAccess( IN PIRP Irp,
993                 IN AFSFcb *Fcb,
994                 IN OUT PFILE_ACCESS_INFORMATION Buffer,
995                 IN OUT PLONG Length)
996 {
997
998     NTSTATUS ntStatus = STATUS_SUCCESS;
999
1000     if( *Length >= sizeof( FILE_ACCESS_INFORMATION))
1001     {
1002
1003         RtlZeroMemory( Buffer,
1004                        *Length);
1005
1006         Buffer->AccessFlags = 0;
1007
1008         *Length -= sizeof( FILE_ACCESS_INFORMATION);
1009     }
1010     else
1011     {
1012
1013         ntStatus = STATUS_BUFFER_TOO_SMALL;
1014     }
1015
1016     return ntStatus;
1017 }
1018
1019 NTSTATUS
1020 AFSQueryMode( IN PIRP Irp,
1021               IN AFSFcb *Fcb,
1022               IN OUT PFILE_MODE_INFORMATION Buffer,
1023               IN OUT PLONG Length)
1024 {
1025
1026     NTSTATUS ntStatus = STATUS_SUCCESS;
1027
1028     if( *Length >= sizeof( FILE_MODE_INFORMATION))
1029     {
1030
1031         RtlZeroMemory( Buffer,
1032                        *Length);
1033
1034         Buffer->Mode = 0;
1035
1036         *Length -= sizeof( FILE_MODE_INFORMATION);
1037     }
1038     else
1039     {
1040
1041         ntStatus = STATUS_BUFFER_TOO_SMALL;
1042     }
1043
1044     return ntStatus;
1045 }
1046
1047 NTSTATUS
1048 AFSQueryAlignment( IN PIRP Irp,
1049                    IN AFSFcb *Fcb,
1050                    IN OUT PFILE_ALIGNMENT_INFORMATION Buffer,
1051                    IN OUT PLONG Length)
1052 {
1053
1054     NTSTATUS ntStatus = STATUS_SUCCESS;
1055
1056     if( *Length >= sizeof( FILE_ALIGNMENT_INFORMATION))
1057     {
1058
1059         RtlZeroMemory( Buffer,
1060                        *Length);
1061
1062         Buffer->AlignmentRequirement = 1;
1063
1064         *Length -= sizeof( FILE_ALIGNMENT_INFORMATION);
1065     }
1066     else
1067     {
1068
1069         ntStatus = STATUS_BUFFER_TOO_SMALL;
1070     }
1071
1072     return ntStatus;
1073 }
1074
1075 NTSTATUS
1076 AFSQueryNameInfo( IN PIRP Irp,
1077                   IN AFSDirectoryCB *DirectoryCB,
1078                   IN OUT PFILE_NAME_INFORMATION Buffer,
1079                   IN OUT PLONG Length)
1080 {
1081
1082     NTSTATUS ntStatus = STATUS_SUCCESS;
1083     ULONG ulCopyLength = 0;
1084     ULONG cchCopied = 0;
1085     AFSFcb *pFcb = NULL;
1086     AFSCcb *pCcb = NULL;
1087     IO_STACK_LOCATION *pIrpSp = IoGetCurrentIrpStackLocation( Irp);
1088     BOOLEAN bAddLeadingSlash = FALSE;
1089     BOOLEAN bAddTrailingSlash = FALSE;
1090     USHORT usFullNameLength = 0;
1091
1092     pFcb = (AFSFcb *)pIrpSp->FileObject->FsContext;
1093
1094     pCcb = (AFSCcb *)pIrpSp->FileObject->FsContext2;
1095
1096     if( *Length >= FIELD_OFFSET( FILE_NAME_INFORMATION, FileName))
1097     {
1098
1099         RtlZeroMemory( Buffer,
1100                        *Length);
1101
1102         if( pCcb->FullFileName.Length == 0 ||
1103             pCcb->FullFileName.Buffer[ 0] != L'\\')
1104         {
1105             bAddLeadingSlash = TRUE;
1106         }
1107
1108         if( pFcb->ObjectInformation->FileType == AFS_FILE_TYPE_DIRECTORY &&
1109             pCcb->FullFileName.Length > 0 &&
1110             pCcb->FullFileName.Buffer[ (pCcb->FullFileName.Length/sizeof( WCHAR)) - 1] != L'\\')
1111         {
1112             bAddTrailingSlash = TRUE;
1113         }
1114
1115         usFullNameLength = sizeof( WCHAR) +
1116                                     AFSServerName.Length +
1117                                     pCcb->FullFileName.Length;
1118
1119         if( bAddLeadingSlash)
1120         {
1121             usFullNameLength += sizeof( WCHAR);
1122         }
1123
1124         if( bAddTrailingSlash)
1125         {
1126             usFullNameLength += sizeof( WCHAR);
1127         }
1128
1129         if( *Length >= (LONG)(FIELD_OFFSET( FILE_NAME_INFORMATION, FileName) + (LONG)usFullNameLength))
1130         {
1131
1132             ulCopyLength = (LONG)usFullNameLength;
1133         }
1134         else
1135         {
1136
1137             ulCopyLength = *Length - FIELD_OFFSET( FILE_NAME_INFORMATION, FileName);
1138
1139             ntStatus = STATUS_BUFFER_OVERFLOW;
1140         }
1141
1142         Buffer->FileNameLength = (ULONG)usFullNameLength;
1143
1144         *Length -= FIELD_OFFSET( FILE_NAME_INFORMATION, FileName);
1145
1146         if( ulCopyLength > 0)
1147         {
1148
1149             Buffer->FileName[ 0] = L'\\';
1150             ulCopyLength -= sizeof( WCHAR);
1151
1152             *Length -= sizeof( WCHAR);
1153             cchCopied += 1;
1154
1155             if( ulCopyLength >= AFSServerName.Length)
1156             {
1157
1158                 RtlCopyMemory( &Buffer->FileName[ 1],
1159                                AFSServerName.Buffer,
1160                                AFSServerName.Length);
1161
1162                 ulCopyLength -= AFSServerName.Length;
1163                 *Length -= AFSServerName.Length;
1164                 cchCopied += AFSServerName.Length/sizeof( WCHAR);
1165
1166                 if ( ulCopyLength > 0 &&
1167                      bAddLeadingSlash)
1168                 {
1169
1170                     Buffer->FileName[ cchCopied] = L'\\';
1171
1172                     ulCopyLength -= sizeof( WCHAR);
1173                     *Length -= sizeof( WCHAR);
1174                     cchCopied++;
1175                 }
1176
1177                 if( ulCopyLength >= pCcb->FullFileName.Length)
1178                 {
1179
1180                     RtlCopyMemory( &Buffer->FileName[ cchCopied],
1181                                    pCcb->FullFileName.Buffer,
1182                                    pCcb->FullFileName.Length);
1183
1184                     ulCopyLength -= pCcb->FullFileName.Length;
1185                     *Length -= pCcb->FullFileName.Length;
1186                     cchCopied += pCcb->FullFileName.Length/sizeof( WCHAR);
1187
1188                     if( ulCopyLength > 0 &&
1189                         bAddTrailingSlash)
1190                     {
1191                         Buffer->FileName[ cchCopied] = L'\\';
1192
1193                         *Length -= sizeof( WCHAR);
1194                     }
1195                 }
1196                 else
1197                 {
1198
1199                     RtlCopyMemory( &Buffer->FileName[ cchCopied],
1200                                    pCcb->FullFileName.Buffer,
1201                                    ulCopyLength);
1202
1203                     *Length -= ulCopyLength;
1204                 }
1205             }
1206         }
1207     }
1208     else
1209     {
1210
1211         ntStatus = STATUS_BUFFER_TOO_SMALL;
1212     }
1213
1214     return ntStatus;
1215 }
1216
1217 NTSTATUS
1218 AFSQueryShortNameInfo( IN PIRP Irp,
1219                        IN AFSDirectoryCB *DirectoryCB,
1220                        IN OUT PFILE_NAME_INFORMATION Buffer,
1221                        IN OUT PLONG Length)
1222 {
1223
1224     NTSTATUS ntStatus = STATUS_BUFFER_TOO_SMALL;
1225     ULONG ulCopyLength = 0;
1226
1227     RtlZeroMemory( Buffer,
1228                    *Length);
1229
1230     if( DirectoryCB->NameInformation.ShortNameLength == 0)
1231     {
1232
1233         //
1234         // The short name IS the long name
1235         //
1236
1237         if( *Length >= (LONG)FIELD_OFFSET( FILE_NAME_INFORMATION, FileName))
1238         {
1239
1240             if( *Length >= (LONG)(FIELD_OFFSET( FILE_NAME_INFORMATION, FileName) + (LONG)DirectoryCB->NameInformation.FileName.Length))
1241             {
1242
1243                 ulCopyLength = (LONG)DirectoryCB->NameInformation.FileName.Length;
1244
1245                 ntStatus = STATUS_SUCCESS;
1246             }
1247             else
1248             {
1249
1250                 ulCopyLength = *Length - FIELD_OFFSET( FILE_NAME_INFORMATION, FileName);
1251
1252                 ntStatus = STATUS_BUFFER_OVERFLOW;
1253             }
1254
1255             Buffer->FileNameLength = DirectoryCB->NameInformation.FileName.Length;
1256
1257             *Length -= FIELD_OFFSET( FILE_NAME_INFORMATION, FileName);
1258
1259             if( ulCopyLength > 0)
1260             {
1261
1262                 RtlCopyMemory( Buffer->FileName,
1263                                DirectoryCB->NameInformation.FileName.Buffer,
1264                                ulCopyLength);
1265
1266                 *Length -= ulCopyLength;
1267             }
1268         }
1269     }
1270     else
1271     {
1272
1273         if( *Length >= (LONG)FIELD_OFFSET( FILE_NAME_INFORMATION, FileName))
1274         {
1275
1276             if( *Length >= (LONG)(FIELD_OFFSET( FILE_NAME_INFORMATION, FileName) + (LONG)DirectoryCB->NameInformation.FileName.Length))
1277             {
1278
1279                 ulCopyLength = (LONG)DirectoryCB->NameInformation.ShortNameLength;
1280
1281                 ntStatus = STATUS_SUCCESS;
1282             }
1283             else
1284             {
1285
1286                 ulCopyLength = *Length - FIELD_OFFSET( FILE_NAME_INFORMATION, FileName);
1287
1288                 ntStatus = STATUS_BUFFER_OVERFLOW;
1289             }
1290
1291             Buffer->FileNameLength = DirectoryCB->NameInformation.ShortNameLength;
1292
1293             *Length -= FIELD_OFFSET( FILE_NAME_INFORMATION, FileName);
1294
1295             if( ulCopyLength > 0)
1296             {
1297
1298                 RtlCopyMemory( Buffer->FileName,
1299                                DirectoryCB->NameInformation.ShortName,
1300                                Buffer->FileNameLength);
1301
1302                 *Length -= ulCopyLength;
1303             }
1304         }
1305     }
1306
1307     return ntStatus;
1308 }
1309
1310 NTSTATUS
1311 AFSQueryNetworkInfo( IN PIRP Irp,
1312                      IN AFSDirectoryCB *DirectoryCB,
1313                      IN OUT PFILE_NETWORK_OPEN_INFORMATION Buffer,
1314                      IN OUT PLONG Length)
1315 {
1316
1317     NTSTATUS ntStatus = STATUS_SUCCESS;
1318     AFSDeviceExt *pDeviceExt = (AFSDeviceExt *)AFSRDRDeviceObject->DeviceExtension;
1319     AFSFcb *pFcb = NULL;
1320     AFSCcb *pCcb = NULL;
1321     PIO_STACK_LOCATION pIrpSp = IoGetCurrentIrpStackLocation( Irp);
1322     AFSFileInfoCB stFileInfo;
1323     AFSDirectoryCB *pParentDirectoryCB = NULL;
1324     UNICODE_STRING uniParentPath;
1325     ULONG ulFileAttribs = 0;
1326
1327     RtlZeroMemory( Buffer,
1328                    *Length);
1329
1330     if( *Length >= sizeof( FILE_NETWORK_OPEN_INFORMATION))
1331     {
1332
1333         ulFileAttribs = DirectoryCB->ObjectInformation->FileAttributes;
1334
1335         pFcb = (AFSFcb *)pIrpSp->FileObject->FsContext;
1336         pCcb = (AFSCcb *)pIrpSp->FileObject->FsContext2;
1337
1338         if( DirectoryCB->ObjectInformation->FileType == AFS_FILE_TYPE_SYMLINK)
1339         {
1340
1341             pParentDirectoryCB = AFSGetParentEntry( pCcb->NameArray);
1342
1343             AFSRetrieveParentPath( &pCcb->FullFileName,
1344                                    &uniParentPath);
1345
1346             RtlZeroMemory( &stFileInfo,
1347                            sizeof( AFSFileInfoCB));
1348
1349             //
1350             // Can't hold the Fcb while evaluating the path, leads to lock inversion
1351             //
1352
1353             AFSReleaseResource( &pFcb->NPFcb->Resource);
1354
1355             if( NT_SUCCESS( AFSRetrieveFileAttributes( pParentDirectoryCB,
1356                                                        DirectoryCB,
1357                                                        &uniParentPath,
1358                                                        NULL,
1359                                                        &stFileInfo)))
1360             {
1361                 ulFileAttribs = stFileInfo.FileAttributes;
1362
1363                 ulFileAttribs |= FILE_ATTRIBUTE_REPARSE_POINT;
1364             }
1365
1366             AFSAcquireShared( &pFcb->NPFcb->Resource,
1367                               TRUE);
1368         }
1369
1370         Buffer->CreationTime.QuadPart = DirectoryCB->ObjectInformation->CreationTime.QuadPart;
1371         Buffer->LastAccessTime.QuadPart = DirectoryCB->ObjectInformation->LastAccessTime.QuadPart;
1372         Buffer->LastWriteTime.QuadPart = DirectoryCB->ObjectInformation->LastWriteTime.QuadPart;
1373         Buffer->ChangeTime.QuadPart = DirectoryCB->ObjectInformation->ChangeTime.QuadPart;
1374
1375         Buffer->AllocationSize.QuadPart = DirectoryCB->ObjectInformation->AllocationSize.QuadPart;
1376         Buffer->EndOfFile.QuadPart = DirectoryCB->ObjectInformation->EndOfFile.QuadPart;
1377
1378         Buffer->FileAttributes = ulFileAttribs;
1379
1380         if( DirectoryCB->NameInformation.FileName.Buffer[ 0] == L'.' &&
1381             BooleanFlagOn( pDeviceExt->DeviceFlags, AFS_DEVICE_FLAG_HIDE_DOT_NAMES))
1382         {
1383
1384             if ( Buffer->FileAttributes != FILE_ATTRIBUTE_NORMAL)
1385             {
1386
1387                 Buffer->FileAttributes |= FILE_ATTRIBUTE_HIDDEN;
1388             }
1389             else
1390             {
1391
1392                 Buffer->FileAttributes = FILE_ATTRIBUTE_HIDDEN;
1393             }
1394         }
1395
1396         *Length -= sizeof( FILE_NETWORK_OPEN_INFORMATION);
1397     }
1398     else
1399     {
1400
1401         ntStatus = STATUS_BUFFER_TOO_SMALL;
1402     }
1403
1404     return ntStatus;
1405 }
1406
1407 NTSTATUS
1408 AFSQueryStreamInfo( IN PIRP Irp,
1409                     IN AFSDirectoryCB *DirectoryCB,
1410                     IN OUT FILE_STREAM_INFORMATION *Buffer,
1411                     IN OUT PLONG Length)
1412 {
1413
1414     NTSTATUS ntStatus = STATUS_BUFFER_TOO_SMALL;
1415     ULONG ulCopyLength = 0;
1416     AFSDeviceExt *pDeviceExt = (AFSDeviceExt *)AFSRDRDeviceObject->DeviceExtension;
1417
1418     if( *Length >= FIELD_OFFSET( FILE_STREAM_INFORMATION, StreamName))
1419     {
1420
1421         RtlZeroMemory( Buffer,
1422                        *Length);
1423
1424         Buffer->NextEntryOffset = 0;
1425
1426
1427         if( !BooleanFlagOn( DirectoryCB->ObjectInformation->FileAttributes, FILE_ATTRIBUTE_DIRECTORY))
1428         {
1429
1430             if( *Length >= (LONG)(FIELD_OFFSET( FILE_STREAM_INFORMATION, StreamName) + 14))  // ::$DATA
1431             {
1432
1433                 ulCopyLength = 14;
1434
1435                 ntStatus = STATUS_SUCCESS;
1436             }
1437             else
1438             {
1439
1440                 ulCopyLength = *Length - FIELD_OFFSET( FILE_STREAM_INFORMATION, StreamName);
1441
1442                 ntStatus = STATUS_BUFFER_OVERFLOW;
1443             }
1444
1445             Buffer->StreamNameLength = 14; // ::$DATA
1446
1447             Buffer->StreamSize.QuadPart = DirectoryCB->ObjectInformation->EndOfFile.QuadPart;
1448
1449             Buffer->StreamAllocationSize.QuadPart = DirectoryCB->ObjectInformation->AllocationSize.QuadPart;
1450
1451             *Length -= FIELD_OFFSET( FILE_STREAM_INFORMATION, StreamName);
1452
1453             if( ulCopyLength > 0)
1454             {
1455
1456                 RtlCopyMemory( Buffer->StreamName,
1457                                L"::$DATA",
1458                                ulCopyLength);
1459
1460                 *Length -= ulCopyLength;
1461             }
1462         }
1463         else
1464         {
1465
1466             Buffer->StreamNameLength = 0;       // No stream for a directory
1467
1468             // The response size is zero
1469
1470             ntStatus = STATUS_SUCCESS;
1471         }
1472     }
1473
1474     return ntStatus;
1475 }
1476
1477 NTSTATUS
1478 AFSQueryAttribTagInfo( IN PIRP Irp,
1479                        IN AFSDirectoryCB *DirectoryCB,
1480                        IN OUT FILE_ATTRIBUTE_TAG_INFORMATION *Buffer,
1481                        IN OUT PLONG Length)
1482 {
1483
1484     NTSTATUS ntStatus = STATUS_BUFFER_TOO_SMALL;
1485     ULONG ulCopyLength = 0;
1486     AFSDeviceExt *pDeviceExt = (AFSDeviceExt *)AFSRDRDeviceObject->DeviceExtension;
1487     AFSFcb *pFcb = NULL;
1488     AFSCcb *pCcb = NULL;
1489     PIO_STACK_LOCATION pIrpSp = IoGetCurrentIrpStackLocation( Irp);
1490     AFSFileInfoCB stFileInfo;
1491     AFSDirectoryCB *pParentDirectoryCB = NULL;
1492     UNICODE_STRING uniParentPath;
1493     ULONG ulFileAttribs = 0;
1494
1495     if( *Length >= sizeof( FILE_ATTRIBUTE_TAG_INFORMATION))
1496     {
1497
1498         RtlZeroMemory( Buffer,
1499                        *Length);
1500
1501         ulFileAttribs = DirectoryCB->ObjectInformation->FileAttributes;
1502
1503         pFcb = (AFSFcb *)pIrpSp->FileObject->FsContext;
1504         pCcb = (AFSCcb *)pIrpSp->FileObject->FsContext2;
1505
1506         if( DirectoryCB->ObjectInformation->FileType == AFS_FILE_TYPE_SYMLINK)
1507         {
1508
1509             pParentDirectoryCB = AFSGetParentEntry( pCcb->NameArray);
1510
1511             AFSRetrieveParentPath( &pCcb->FullFileName,
1512                                    &uniParentPath);
1513
1514             RtlZeroMemory( &stFileInfo,
1515                            sizeof( AFSFileInfoCB));
1516
1517             //
1518             // Can't hold the Fcb while evaluating the path, leads to lock inversion
1519             //
1520
1521             AFSReleaseResource( &pFcb->NPFcb->Resource);
1522
1523             if( NT_SUCCESS( AFSRetrieveFileAttributes( pParentDirectoryCB,
1524                                                        DirectoryCB,
1525                                                        &uniParentPath,
1526                                                        NULL,
1527                                                        &stFileInfo)))
1528             {
1529                 ulFileAttribs = stFileInfo.FileAttributes;
1530
1531                 ulFileAttribs |= FILE_ATTRIBUTE_REPARSE_POINT;
1532             }
1533
1534             AFSAcquireShared( &pFcb->NPFcb->Resource,
1535                               TRUE);
1536         }
1537
1538         Buffer->FileAttributes = ulFileAttribs;
1539
1540         if( DirectoryCB->NameInformation.FileName.Buffer[ 0] == L'.' &&
1541             BooleanFlagOn( pDeviceExt->DeviceFlags, AFS_DEVICE_FLAG_HIDE_DOT_NAMES))
1542         {
1543
1544             if ( Buffer->FileAttributes != FILE_ATTRIBUTE_NORMAL)
1545             {
1546
1547                 Buffer->FileAttributes |= FILE_ATTRIBUTE_HIDDEN;
1548             }
1549             else
1550             {
1551
1552                 Buffer->FileAttributes = FILE_ATTRIBUTE_HIDDEN;
1553             }
1554         }
1555
1556         if( BooleanFlagOn( DirectoryCB->ObjectInformation->FileAttributes, FILE_ATTRIBUTE_REPARSE_POINT))
1557         {
1558             Buffer->ReparseTag = IO_REPARSE_TAG_OPENAFS_DFS;
1559         }
1560
1561         *Length -= sizeof( FILE_ATTRIBUTE_TAG_INFORMATION);
1562
1563         ntStatus = STATUS_SUCCESS;
1564     }
1565
1566     return ntStatus;
1567 }
1568
1569 NTSTATUS
1570 AFSQueryRemoteProtocolInfo( IN PIRP Irp,
1571                             IN AFSDirectoryCB *DirectoryCB,
1572                             IN OUT FILE_REMOTE_PROTOCOL_INFORMATION *Buffer,
1573                             IN OUT PLONG Length)
1574 {
1575
1576     NTSTATUS ntStatus = STATUS_BUFFER_TOO_SMALL;
1577     ULONG ulCopyLength = 0;
1578     AFSDeviceExt *pDeviceExt = (AFSDeviceExt *)AFSRDRDeviceObject->DeviceExtension;
1579
1580     if( *Length >= sizeof( FILE_REMOTE_PROTOCOL_INFORMATION))
1581     {
1582
1583         RtlZeroMemory( Buffer,
1584                        *Length);
1585
1586         Buffer->StructureVersion = 1;
1587
1588         Buffer->StructureSize = sizeof(FILE_REMOTE_PROTOCOL_INFORMATION);
1589
1590         Buffer->Protocol = WNNC_NET_OPENAFS;
1591
1592         Buffer->ProtocolMajorVersion = 3;
1593
1594         Buffer->ProtocolMinorVersion = 0;
1595
1596         Buffer->ProtocolRevision = 0;
1597
1598         *Length -= sizeof( FILE_REMOTE_PROTOCOL_INFORMATION);
1599
1600         ntStatus = STATUS_SUCCESS;
1601     }
1602
1603     return ntStatus;
1604 }
1605
1606 NTSTATUS
1607 AFSSetBasicInfo( IN PIRP Irp,
1608                  IN AFSDirectoryCB *DirectoryCB)
1609 {
1610     NTSTATUS ntStatus = STATUS_SUCCESS;
1611     PFILE_BASIC_INFORMATION pBuffer;
1612     PIO_STACK_LOCATION pIrpSp = IoGetCurrentIrpStackLocation( Irp);
1613     ULONG ulNotifyFilter = 0;
1614     AFSCcb *pCcb = NULL;
1615
1616     __Enter
1617     {
1618
1619         pCcb = (AFSCcb *)pIrpSp->FileObject->FsContext2;
1620
1621         pBuffer = (PFILE_BASIC_INFORMATION)Irp->AssociatedIrp.SystemBuffer;
1622
1623         pCcb->FileUnwindInfo.FileAttributes = (ULONG)-1;
1624
1625         if( pBuffer->FileAttributes != (ULONGLONG)0)
1626         {
1627
1628             if( DirectoryCB->ObjectInformation->Fcb->Header.NodeTypeCode == AFS_FILE_FCB &&
1629                 BooleanFlagOn( pBuffer->FileAttributes, FILE_ATTRIBUTE_DIRECTORY))
1630             {
1631
1632                 try_return( ntStatus = STATUS_INVALID_PARAMETER);
1633             }
1634
1635             if( DirectoryCB->ObjectInformation->Fcb->Header.NodeTypeCode == AFS_DIRECTORY_FCB)
1636             {
1637
1638                 pBuffer->FileAttributes |= FILE_ATTRIBUTE_DIRECTORY;
1639             }
1640
1641             pCcb->FileUnwindInfo.FileAttributes = DirectoryCB->ObjectInformation->FileAttributes;
1642
1643             DirectoryCB->ObjectInformation->FileAttributes = pBuffer->FileAttributes;
1644
1645             ulNotifyFilter |= FILE_NOTIFY_CHANGE_ATTRIBUTES;
1646
1647             SetFlag( DirectoryCB->ObjectInformation->Fcb->Flags, AFS_FCB_FLAG_FILE_MODIFIED);
1648         }
1649
1650         pCcb->FileUnwindInfo.CreationTime.QuadPart = (ULONGLONG)-1;
1651
1652         if( pBuffer->CreationTime.QuadPart != (ULONGLONG)-1 &&
1653             pBuffer->CreationTime.QuadPart != (ULONGLONG)0)
1654         {
1655
1656             pCcb->FileUnwindInfo.CreationTime.QuadPart = DirectoryCB->ObjectInformation->CreationTime.QuadPart;
1657
1658             DirectoryCB->ObjectInformation->CreationTime.QuadPart = pBuffer->CreationTime.QuadPart;
1659
1660             ulNotifyFilter |= FILE_NOTIFY_CHANGE_CREATION;
1661
1662             SetFlag( DirectoryCB->ObjectInformation->Fcb->Flags, AFS_FCB_FLAG_FILE_MODIFIED | AFS_FCB_FLAG_UPDATE_CREATE_TIME);
1663         }
1664
1665         pCcb->FileUnwindInfo.LastAccessTime.QuadPart = (ULONGLONG)-1;
1666
1667         if( pBuffer->LastAccessTime.QuadPart != (ULONGLONG)-1 &&
1668             pBuffer->LastAccessTime.QuadPart != (ULONGLONG)0)
1669         {
1670
1671             pCcb->FileUnwindInfo.LastAccessTime.QuadPart = DirectoryCB->ObjectInformation->LastAccessTime.QuadPart;
1672
1673             DirectoryCB->ObjectInformation->LastAccessTime.QuadPart = pBuffer->LastAccessTime.QuadPart;
1674
1675             ulNotifyFilter |= FILE_NOTIFY_CHANGE_LAST_ACCESS;
1676
1677             SetFlag( DirectoryCB->ObjectInformation->Fcb->Flags, AFS_FCB_FLAG_FILE_MODIFIED | AFS_FCB_FLAG_UPDATE_ACCESS_TIME);
1678         }
1679
1680         pCcb->FileUnwindInfo.LastWriteTime.QuadPart = (ULONGLONG)-1;
1681
1682         if( pBuffer->LastWriteTime.QuadPart != (ULONGLONG)-1 &&
1683             pBuffer->LastWriteTime.QuadPart != (ULONGLONG)0)
1684         {
1685
1686             pCcb->FileUnwindInfo.LastWriteTime.QuadPart = DirectoryCB->ObjectInformation->LastWriteTime.QuadPart;
1687
1688             DirectoryCB->ObjectInformation->LastWriteTime.QuadPart = pBuffer->LastWriteTime.QuadPart;
1689
1690             ulNotifyFilter |= FILE_NOTIFY_CHANGE_LAST_WRITE;
1691
1692             SetFlag( DirectoryCB->ObjectInformation->Fcb->Flags, AFS_FCB_FLAG_FILE_MODIFIED | AFS_FCB_FLAG_UPDATE_LAST_WRITE_TIME);
1693         }
1694
1695         pCcb->FileUnwindInfo.ChangeTime.QuadPart = (ULONGLONG)-1;
1696
1697         if( pBuffer->ChangeTime.QuadPart != (ULONGLONG)-1 &&
1698             pBuffer->ChangeTime.QuadPart != (ULONGLONG)0)
1699         {
1700
1701             pCcb->FileUnwindInfo.ChangeTime.QuadPart = DirectoryCB->ObjectInformation->ChangeTime.QuadPart;
1702
1703             DirectoryCB->ObjectInformation->ChangeTime.QuadPart = pBuffer->ChangeTime.QuadPart;
1704
1705             ulNotifyFilter |= FILE_NOTIFY_CHANGE_LAST_ACCESS;
1706
1707             SetFlag( DirectoryCB->ObjectInformation->Fcb->Flags, AFS_FCB_FLAG_FILE_MODIFIED | AFS_FCB_FLAG_UPDATE_CHANGE_TIME);
1708         }
1709
1710         if( ulNotifyFilter > 0)
1711         {
1712
1713             if( DirectoryCB->ObjectInformation->ParentObjectInformation != NULL)
1714             {
1715
1716                 AFSFsRtlNotifyFullReportChange( DirectoryCB->ObjectInformation->ParentObjectInformation,
1717                                                 pCcb,
1718                                                 (ULONG)ulNotifyFilter,
1719                                                 (ULONG)FILE_ACTION_MODIFIED);
1720             }
1721         }
1722
1723 try_exit:
1724
1725         NOTHING;
1726     }
1727
1728     return ntStatus;
1729 }
1730
1731 NTSTATUS
1732 AFSSetDispositionInfo( IN PIRP Irp,
1733                        IN AFSDirectoryCB *DirectoryCB)
1734 {
1735     NTSTATUS ntStatus = STATUS_SUCCESS;
1736     PFILE_DISPOSITION_INFORMATION pBuffer;
1737     PIO_STACK_LOCATION pIrpSp = IoGetCurrentIrpStackLocation( Irp);
1738     AFSFcb *pFcb = NULL;
1739     AFSCcb *pCcb = NULL;
1740
1741     __Enter
1742     {
1743
1744         pBuffer = (PFILE_DISPOSITION_INFORMATION)Irp->AssociatedIrp.SystemBuffer;
1745
1746         pFcb = (AFSFcb *)pIrpSp->FileObject->FsContext;
1747
1748         pCcb = (AFSCcb *)pIrpSp->FileObject->FsContext2;
1749
1750         //
1751         // Can't delete the root
1752         //
1753
1754         if( pFcb->Header.NodeTypeCode == AFS_ROOT_FCB)
1755         {
1756
1757             AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
1758                           AFS_TRACE_LEVEL_ERROR,
1759                           "AFSSetDispositionInfo Attempt to delete root entry\n");
1760
1761             try_return( ntStatus = STATUS_CANNOT_DELETE);
1762         }
1763
1764         //
1765         // If the file is read only then do not allow the delete
1766         //
1767
1768         if( BooleanFlagOn( DirectoryCB->ObjectInformation->FileAttributes, FILE_ATTRIBUTE_READONLY))
1769         {
1770
1771             AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
1772                           AFS_TRACE_LEVEL_ERROR,
1773                           "AFSSetDispositionInfo Attempt to delete read only entry %wZ\n",
1774                           &DirectoryCB->NameInformation.FileName);
1775
1776             try_return( ntStatus = STATUS_CANNOT_DELETE);
1777         }
1778
1779         if( pBuffer->DeleteFile)
1780         {
1781
1782             //
1783             // Check if the caller can delete the file
1784             //
1785
1786             ntStatus = AFSNotifyDelete( DirectoryCB,
1787                                         TRUE);
1788
1789             if( !NT_SUCCESS( ntStatus))
1790             {
1791
1792                 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
1793                               AFS_TRACE_LEVEL_ERROR,
1794                               "AFSSetDispositionInfo Cannot delete entry %wZ Status %08lX\n",
1795                               &DirectoryCB->NameInformation.FileName,
1796                               ntStatus);
1797
1798                 try_return( ntStatus);
1799             }
1800
1801             if( pFcb->Header.NodeTypeCode == AFS_DIRECTORY_FCB)
1802             {
1803
1804                 //
1805                 // Check if this is a directory that there are not currently other opens
1806                 //
1807
1808                 if( pFcb->ObjectInformation->Specific.Directory.ChildOpenHandleCount > 0)
1809                 {
1810
1811                     AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
1812                                   AFS_TRACE_LEVEL_ERROR,
1813                                   "AFSSetDispositionInfo Attempt to delete directory %wZ with open %u handles\n",
1814                                   &DirectoryCB->NameInformation.FileName,
1815                                   pFcb->ObjectInformation->Specific.Directory.ChildOpenHandleCount);
1816
1817                     try_return( ntStatus = STATUS_DIRECTORY_NOT_EMPTY);
1818                 }
1819
1820                 if( !AFSIsDirectoryEmptyForDelete( pFcb))
1821                 {
1822
1823                     AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
1824                                   AFS_TRACE_LEVEL_ERROR,
1825                                   "AFSSetDispositionInfo Attempt to delete non-empty directory %wZ\n",
1826                                   &DirectoryCB->NameInformation.FileName);
1827
1828                     try_return( ntStatus = STATUS_DIRECTORY_NOT_EMPTY);
1829                 }
1830             }
1831             else
1832             {
1833
1834                 //
1835                 // Attempt to flush any outstanding data
1836                 //
1837
1838                 if( !MmFlushImageSection( &pFcb->NPFcb->SectionObjectPointers,
1839                                           MmFlushForDelete))
1840                 {
1841
1842                     AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
1843                                   AFS_TRACE_LEVEL_ERROR,
1844                                   "AFSSetDispositionInfo Failed to flush image section for delete Entry %wZ\n",
1845                                   &DirectoryCB->NameInformation.FileName);
1846
1847                     try_return( ntStatus = STATUS_CANNOT_DELETE);
1848                 }
1849
1850                 //
1851                 // Purge the cache as well
1852                 //
1853
1854                 if( pFcb->NPFcb->SectionObjectPointers.DataSectionObject != NULL)
1855                 {
1856
1857                     CcPurgeCacheSection( &pFcb->NPFcb->SectionObjectPointers,
1858                                          NULL,
1859                                          0,
1860                                          TRUE);
1861                 }
1862             }
1863
1864             AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
1865                           AFS_TRACE_LEVEL_VERBOSE,
1866                           "AFSSetDispositionInfo Setting PENDING_DELETE on DirEntry  %p Name %wZ\n",
1867                           DirectoryCB,
1868                           &DirectoryCB->NameInformation.FileName);
1869
1870             SetFlag( pCcb->DirectoryCB->Flags, AFS_DIR_ENTRY_PENDING_DELETE);
1871         }
1872         else
1873         {
1874
1875             ClearFlag( pCcb->DirectoryCB->Flags, AFS_DIR_ENTRY_PENDING_DELETE);
1876         }
1877
1878         //
1879         // OK, should be good to go, set the flag in the file object
1880         //
1881
1882         pIrpSp->FileObject->DeletePending = pBuffer->DeleteFile;
1883
1884 try_exit:
1885
1886         NOTHING;
1887     }
1888
1889     return ntStatus;
1890 }
1891
1892 NTSTATUS
1893 AFSSetRenameInfo( IN PIRP Irp)
1894 {
1895
1896     NTSTATUS ntStatus = STATUS_SUCCESS;
1897     PIO_STACK_LOCATION pIrpSp = IoGetCurrentIrpStackLocation( Irp);
1898     IO_STATUS_BLOCK stIoSb = {0,0};
1899     AFSFcb *pSrcFcb = NULL, *pTargetDcb = NULL, *pTargetFcb = NULL;
1900     AFSCcb *pSrcCcb = NULL, *pTargetDirCcb = NULL;
1901     PFILE_OBJECT pSrcFileObj = pIrpSp->FileObject;
1902     PFILE_OBJECT pTargetFileObj = pIrpSp->Parameters.SetFile.FileObject;
1903     PFILE_RENAME_INFORMATION pRenameInfo = NULL;
1904     UNICODE_STRING uniTargetName, uniSourceName;
1905     BOOLEAN bReplaceIfExists = FALSE;
1906     UNICODE_STRING uniShortName;
1907     AFSDirectoryCB *pTargetDirEntry = NULL;
1908     ULONG ulTargetCRC = 0;
1909     BOOLEAN bTargetEntryExists = FALSE;
1910     AFSObjectInfoCB *pSrcObject = NULL, *pTargetObject = NULL;
1911     AFSObjectInfoCB *pSrcParentObject = NULL, *pTargetParentObject = NULL;
1912     AFSFileID stNewFid, stTmpTargetFid;
1913     ULONG ulNotificationAction = 0, ulNotifyFilter = 0;
1914     UNICODE_STRING uniFullTargetPath;
1915     BOOLEAN bCommonParent = FALSE;
1916     ULONG oldFileIndex;
1917     BOOLEAN bReleaseVolumeLock = FALSE;
1918     BOOLEAN bReleaseTargetDirLock = FALSE;
1919     BOOLEAN bReleaseSourceDirLock = FALSE;
1920
1921     __Enter
1922     {
1923
1924         bReplaceIfExists = pIrpSp->Parameters.SetFile.ReplaceIfExists;
1925
1926         pSrcFcb = (AFSFcb *)pSrcFileObj->FsContext;
1927         pSrcCcb = (AFSCcb *)pSrcFileObj->FsContext2;
1928
1929         pSrcObject = pSrcFcb->ObjectInformation;
1930
1931         //
1932         // Perform some basic checks to ensure FS integrity
1933         //
1934
1935         if( pSrcFcb->Header.NodeTypeCode == AFS_ROOT_FCB)
1936         {
1937
1938             //
1939             // Can't rename the root directory
1940             //
1941
1942             AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
1943                           AFS_TRACE_LEVEL_ERROR,
1944                           "AFSSetRenameInfo Attempt to rename root entry\n");
1945
1946             try_return( ntStatus = STATUS_INVALID_PARAMETER);
1947         }
1948
1949         if( pSrcFcb->Header.NodeTypeCode == AFS_DIRECTORY_FCB)
1950         {
1951
1952             //
1953             // If there are any open children then fail the rename
1954             //
1955
1956             if( pSrcFcb->ObjectInformation->Specific.Directory.ChildOpenHandleCount > 0)
1957             {
1958
1959                 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
1960                               AFS_TRACE_LEVEL_ERROR,
1961                               "AFSSetRenameInfo Attempt to rename directory with open children %wZ\n",
1962                               &pSrcCcb->DirectoryCB->NameInformation.FileName);
1963
1964                 try_return( ntStatus = STATUS_ACCESS_DENIED);
1965             }
1966         }
1967         else
1968         {
1969
1970             if( pSrcFcb->OpenHandleCount > 1)
1971             {
1972
1973                 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
1974                               AFS_TRACE_LEVEL_ERROR,
1975                               "AFSSetRenameInfo Attempt to rename directory with open references %wZ\n",
1976                               &pSrcCcb->DirectoryCB->NameInformation.FileName);
1977
1978                 try_return( ntStatus = STATUS_ACCESS_DENIED);
1979             }
1980         }
1981
1982         //
1983         // Resolve the target fileobject
1984         //
1985
1986         if( pTargetFileObj == NULL)
1987         {
1988
1989             //
1990             // This is a simple rename. Here the target directory is the same as the source parent directory
1991             // and the name is retrieved from the system buffer information
1992             //
1993
1994             pRenameInfo = (PFILE_RENAME_INFORMATION)Irp->AssociatedIrp.SystemBuffer;
1995
1996             pTargetParentObject = pSrcFcb->ObjectInformation->ParentObjectInformation;
1997
1998             pTargetDcb = pTargetParentObject->Fcb;
1999
2000             uniTargetName.Length = (USHORT)pRenameInfo->FileNameLength;
2001             uniTargetName.Buffer = (PWSTR)&pRenameInfo->FileName;
2002         }
2003         else
2004         {
2005
2006             //
2007             // So here we have the target directory taken from the targetfile object
2008             //
2009
2010             pTargetDcb = (AFSFcb *)pTargetFileObj->FsContext;
2011
2012             pTargetDirCcb = (AFSCcb *)pTargetFileObj->FsContext2;
2013
2014             pTargetParentObject = (AFSObjectInfoCB *)pTargetDcb->ObjectInformation;
2015
2016             //
2017             // Grab the target name which we setup in the IRP_MJ_CREATE handler. By how we set this up
2018             // it is only the target component of the rename operation
2019             //
2020
2021             uniTargetName = *((PUNICODE_STRING)&pTargetFileObj->FileName);
2022         }
2023
2024         //
2025         // We do not allow cross-volume renames to occur
2026         //
2027
2028         if( pTargetParentObject->VolumeCB != pSrcObject->VolumeCB)
2029         {
2030
2031             AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
2032                           AFS_TRACE_LEVEL_ERROR,
2033                           "AFSSetRenameInfo Attempt to rename directory to different volume %wZ\n",
2034                           &pSrcCcb->DirectoryCB->NameInformation.FileName);
2035
2036             try_return( ntStatus = STATUS_NOT_SAME_DEVICE);
2037         }
2038
2039         //
2040         // If the target exists be sure the ReplaceIfExists flag is set
2041         //
2042
2043         AFSAcquireExcl( pTargetParentObject->VolumeCB->VolumeLock,
2044                         TRUE);
2045
2046         bReleaseVolumeLock = TRUE;
2047
2048         ulTargetCRC = AFSGenerateCRC( &uniTargetName,
2049                                       FALSE);
2050
2051         AFSAcquireExcl( pTargetParentObject->Specific.Directory.DirectoryNodeHdr.TreeLock,
2052                         TRUE);
2053
2054         bReleaseTargetDirLock = TRUE;
2055
2056         if( pTargetParentObject != pSrcFcb->ObjectInformation->ParentObjectInformation)
2057         {
2058             AFSAcquireExcl( pSrcFcb->ObjectInformation->ParentObjectInformation->Specific.Directory.DirectoryNodeHdr.TreeLock,
2059                             TRUE);
2060
2061             bReleaseSourceDirLock = TRUE;
2062         }
2063
2064         AFSLocateCaseSensitiveDirEntry( pTargetParentObject->Specific.Directory.DirectoryNodeHdr.CaseSensitiveTreeHead,
2065                                         ulTargetCRC,
2066                                         &pTargetDirEntry);
2067
2068         if( pTargetDirEntry == NULL)
2069         {
2070
2071             //
2072             // Missed so perform a case insensitive lookup
2073             //
2074
2075             ulTargetCRC = AFSGenerateCRC( &uniTargetName,
2076                                           TRUE);
2077
2078             AFSLocateCaseInsensitiveDirEntry( pTargetParentObject->Specific.Directory.DirectoryNodeHdr.CaseInsensitiveTreeHead,
2079                                               ulTargetCRC,
2080                                               &pTargetDirEntry);
2081         }
2082
2083         if( pTargetDirEntry == NULL && RtlIsNameLegalDOS8Dot3( &uniTargetName,
2084                                                                NULL,
2085                                                                NULL))
2086         {
2087             //
2088             // Try the short name
2089             //
2090             AFSLocateShortNameDirEntry( pTargetParentObject->Specific.Directory.ShortNameTree,
2091                                         ulTargetCRC,
2092                                         &pTargetDirEntry);
2093         }
2094
2095         //
2096         // Increment our ref count on the dir entry
2097         //
2098
2099         if( pTargetDirEntry != NULL)
2100         {
2101
2102             ASSERT( pTargetParentObject == pTargetDirEntry->ObjectInformation->ParentObjectInformation);
2103
2104             InterlockedIncrement( &pTargetDirEntry->OpenReferenceCount);
2105
2106             if( !bReplaceIfExists)
2107             {
2108
2109                 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
2110                               AFS_TRACE_LEVEL_ERROR,
2111                               "AFSSetRenameInfo Attempt to rename directory with target collision %wZ Target %wZ\n",
2112                               &pSrcCcb->DirectoryCB->NameInformation.FileName,
2113                               &pTargetDirEntry->NameInformation.FileName);
2114
2115                 try_return( ntStatus = STATUS_OBJECT_NAME_COLLISION);
2116             }
2117
2118             AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
2119                           AFS_TRACE_LEVEL_ERROR,
2120                           "AFSSetRenameInfo Target %wZ exists DE %p Count %08lX, performing delete of target\n",
2121                           &pTargetDirEntry->NameInformation.FileName,
2122                           pTargetDirEntry,
2123                           pTargetDirEntry->OpenReferenceCount);
2124
2125             //
2126             // Pull the directory entry from the parent
2127             //
2128
2129             AFSRemoveDirNodeFromParent( pTargetParentObject,
2130                                         pTargetDirEntry,
2131                                         FALSE);
2132
2133             bTargetEntryExists = TRUE;
2134         }
2135         else
2136         {
2137             AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
2138                           AFS_TRACE_LEVEL_ERROR,
2139                           "AFSSetRenameInfo Target Target does NOT exist, normal rename\n");
2140         }
2141
2142         //
2143         // Extract off the final component name from the Fcb
2144         //
2145
2146         uniSourceName.Length = (USHORT)pSrcCcb->DirectoryCB->NameInformation.FileName.Length;
2147         uniSourceName.MaximumLength = uniSourceName.Length;
2148
2149         uniSourceName.Buffer = pSrcCcb->DirectoryCB->NameInformation.FileName.Buffer;
2150
2151         //
2152         // The quick check to see if they are not really performing a rename
2153         // Do the names match? Only do this where the parent directories are
2154         // the same
2155         //
2156
2157         if( pTargetParentObject == pSrcFcb->ObjectInformation->ParentObjectInformation)
2158         {
2159
2160             bCommonParent = TRUE;
2161
2162             if( FsRtlAreNamesEqual( &uniTargetName,
2163                                     &uniSourceName,
2164                                     FALSE,
2165                                     NULL))
2166             {
2167                 try_return( ntStatus = STATUS_SUCCESS);
2168             }
2169         }
2170         else
2171         {
2172
2173             bCommonParent = FALSE;
2174         }
2175
2176         //
2177         // We need to remove the DirEntry from the parent node, update the index
2178         // and reinsert it into the parent tree. Note that for entries with the
2179         // same parent we do not pull the node from the enumeration list
2180         //
2181
2182         AFSRemoveDirNodeFromParent( pSrcFcb->ObjectInformation->ParentObjectInformation,
2183                                     pSrcCcb->DirectoryCB,
2184                                     !bCommonParent);
2185
2186         oldFileIndex = pSrcCcb->DirectoryCB->FileIndex;
2187
2188         if( !bCommonParent)
2189         {
2190
2191             //
2192             // We always need to update the FileIndex since this entry will be put at the 'end'
2193             // of the enumeraiton list. If we don't it will cause recursion ... We do this
2194             // here to cover any failures which might occur below
2195             //
2196
2197             pSrcCcb->DirectoryCB->FileIndex =
2198                             (ULONG)InterlockedIncrement( &pTargetDcb->ObjectInformation->ParentObjectInformation->Specific.Directory.DirectoryNodeHdr.ContentIndex);
2199         }
2200
2201         //
2202         // OK, this is a simple rename. Issue the rename
2203         // request to the service.
2204         //
2205
2206         ntStatus = AFSNotifyRename( pSrcFcb->ObjectInformation,
2207                                     pSrcFcb->ObjectInformation->ParentObjectInformation,
2208                                     pTargetDcb->ObjectInformation,
2209                                     pSrcCcb->DirectoryCB,
2210                                     &uniTargetName,
2211                                     &stNewFid);
2212
2213         if( !NT_SUCCESS( ntStatus))
2214         {
2215
2216             //
2217             // Attempt to re-insert the directory entry
2218             //
2219
2220             pSrcCcb->DirectoryCB->FileIndex = oldFileIndex;
2221             AFSInsertDirectoryNode( pSrcFcb->ObjectInformation->ParentObjectInformation,
2222                                     pSrcCcb->DirectoryCB,
2223                                     !bCommonParent);
2224
2225             AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
2226                           AFS_TRACE_LEVEL_ERROR,
2227                           "AFSSetRenameInfo Failed rename of %wZ to target %wZ Status %08lX\n",
2228                           &pSrcCcb->DirectoryCB->NameInformation.FileName,
2229                           &uniTargetName,
2230                           ntStatus);
2231
2232             try_return( ntStatus);
2233         }
2234
2235         //
2236         // Set the notification up for the source file
2237         //
2238
2239         if( pSrcCcb->DirectoryCB->ObjectInformation->ParentObjectInformation == pTargetParentObject &&
2240             !bTargetEntryExists)
2241         {
2242
2243             ulNotificationAction = FILE_ACTION_RENAMED_OLD_NAME;
2244         }
2245         else
2246         {
2247
2248             ulNotificationAction = FILE_ACTION_REMOVED;
2249         }
2250
2251         if( pSrcCcb->DirectoryCB->ObjectInformation->FileType == AFS_FILE_TYPE_DIRECTORY)
2252         {
2253
2254             ulNotifyFilter = FILE_NOTIFY_CHANGE_DIR_NAME;
2255         }
2256         else
2257         {
2258
2259             ulNotifyFilter = FILE_NOTIFY_CHANGE_FILE_NAME;
2260         }
2261
2262         AFSFsRtlNotifyFullReportChange( pSrcCcb->DirectoryCB->ObjectInformation->ParentObjectInformation,
2263                                         pSrcCcb,
2264                                         (ULONG)ulNotifyFilter,
2265                                         (ULONG)ulNotificationAction);
2266
2267         //
2268         // Update the name in the dir entry.
2269         //
2270
2271         ntStatus = AFSUpdateDirEntryName( pSrcCcb->DirectoryCB,
2272                                           &uniTargetName);
2273
2274         if( !NT_SUCCESS( ntStatus))
2275         {
2276
2277             //
2278             // Attempt to re-insert the directory entry
2279             //
2280
2281             pSrcCcb->DirectoryCB->FileIndex = oldFileIndex;
2282             AFSInsertDirectoryNode( pSrcFcb->ObjectInformation->ParentObjectInformation,
2283                                     pSrcCcb->DirectoryCB,
2284                                     !bCommonParent);
2285
2286             AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
2287                           AFS_TRACE_LEVEL_ERROR,
2288                           "AFSSetRenameInfo Failed update of dir entry %wZ to target %wZ Status %08lX\n",
2289                           &pSrcCcb->DirectoryCB->NameInformation.FileName,
2290                           &uniTargetName,
2291                           ntStatus);
2292
2293             try_return( ntStatus);
2294         }
2295
2296         //
2297         // Update the object information block, if needed
2298         //
2299
2300         if( !AFSIsEqualFID( &pSrcObject->FileId,
2301                             &stNewFid))
2302         {
2303
2304             //
2305             // Remove the old information entry
2306             //
2307
2308             AFSRemoveHashEntry( &pSrcObject->VolumeCB->ObjectInfoTree.TreeHead,
2309                                 &pSrcObject->TreeEntry);
2310
2311             RtlCopyMemory( &pSrcObject->FileId,
2312                            &stNewFid,
2313                            sizeof( AFSFileID));
2314
2315             //
2316             // Insert the entry into the new object table.
2317             //
2318
2319             pSrcObject->TreeEntry.HashIndex = AFSCreateLowIndex( &pSrcObject->FileId);
2320
2321             if( pSrcObject->VolumeCB->ObjectInfoTree.TreeHead == NULL)
2322             {
2323
2324                 pSrcObject->VolumeCB->ObjectInfoTree.TreeHead = &pSrcObject->TreeEntry;
2325             }
2326             else
2327             {
2328
2329                 AFSInsertHashEntry( pSrcObject->VolumeCB->ObjectInfoTree.TreeHead,
2330                                     &pSrcObject->TreeEntry);
2331             }
2332         }
2333
2334         //
2335         // Update the hash values for the name trees.
2336         //
2337
2338         pSrcCcb->DirectoryCB->CaseSensitiveTreeEntry.HashIndex = AFSGenerateCRC( &pSrcCcb->DirectoryCB->NameInformation.FileName,
2339                                                                                  FALSE);
2340
2341         pSrcCcb->DirectoryCB->CaseInsensitiveTreeEntry.HashIndex = AFSGenerateCRC( &pSrcCcb->DirectoryCB->NameInformation.FileName,
2342                                                                                    TRUE);
2343
2344         if( pSrcCcb->DirectoryCB->NameInformation.ShortNameLength > 0 &&
2345             !RtlIsNameLegalDOS8Dot3( &pSrcCcb->DirectoryCB->NameInformation.FileName,
2346                                      NULL,
2347                                      NULL))
2348         {
2349
2350             uniShortName.Length = pSrcCcb->DirectoryCB->NameInformation.ShortNameLength;
2351             uniShortName.MaximumLength = uniShortName.Length;
2352             uniShortName.Buffer = pSrcCcb->DirectoryCB->NameInformation.ShortName;
2353
2354             pSrcCcb->DirectoryCB->Type.Data.ShortNameTreeEntry.HashIndex = AFSGenerateCRC( &uniShortName,
2355                                                                                            TRUE);
2356
2357             AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
2358                           AFS_TRACE_LEVEL_VERBOSE,
2359                           "AFSSetRenameInfo Initialized short name hash for %wZ longname %wZ\n",
2360                           &uniShortName,
2361                           &pSrcCcb->DirectoryCB->NameInformation.FileName);
2362         }
2363         else
2364         {
2365
2366             pSrcCcb->DirectoryCB->Type.Data.ShortNameTreeEntry.HashIndex = 0;
2367         }
2368
2369         if( !bCommonParent)
2370         {
2371
2372             //
2373             // Update the file index for the object in the new parent
2374             //
2375
2376             pSrcCcb->DirectoryCB->FileIndex = (ULONG)InterlockedIncrement( &pTargetParentObject->Specific.Directory.DirectoryNodeHdr.ContentIndex);
2377         }
2378
2379         //
2380         // Re-insert the directory entry
2381         //
2382
2383         AFSInsertDirectoryNode( pTargetParentObject,
2384                                 pSrcCcb->DirectoryCB,
2385                                 !bCommonParent);
2386
2387         //
2388         // Update the parent pointer in the source object if they are different
2389         //
2390
2391         if( pSrcCcb->DirectoryCB->ObjectInformation->ParentObjectInformation != pTargetParentObject)
2392         {
2393
2394             InterlockedDecrement( &pSrcCcb->DirectoryCB->ObjectInformation->ParentObjectInformation->Specific.Directory.ChildOpenHandleCount);
2395
2396             InterlockedDecrement( &pSrcCcb->DirectoryCB->ObjectInformation->ParentObjectInformation->Specific.Directory.ChildOpenReferenceCount);
2397
2398             InterlockedIncrement( &pTargetParentObject->Specific.Directory.ChildOpenHandleCount);
2399
2400             InterlockedIncrement( &pTargetParentObject->Specific.Directory.ChildOpenReferenceCount);
2401
2402             pSrcCcb->DirectoryCB->ObjectInformation->ParentObjectInformation = pTargetParentObject;
2403
2404             ulNotificationAction = FILE_ACTION_ADDED;
2405         }
2406         else
2407         {
2408
2409             ulNotificationAction = FILE_ACTION_RENAMED_NEW_NAME;
2410         }
2411
2412         //
2413         // Now update the notification for the target file
2414         //
2415
2416         AFSFsRtlNotifyFullReportChange( pTargetParentObject->ParentObjectInformation,
2417                                         pSrcCcb,
2418                                         (ULONG)ulNotifyFilter,
2419                                         (ULONG)ulNotificationAction);
2420
2421         //
2422         // If we performed the rename of the target because it existed, we now need to
2423         // delete the tmp target we created above
2424         //
2425
2426         if( bTargetEntryExists)
2427         {
2428
2429             AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
2430                           AFS_TRACE_LEVEL_VERBOSE,
2431                           "AFSSetRenameInfo Setting DELETE flag in dir entry %p name %wZ\n",
2432                           pTargetDirEntry,
2433                           &pTargetDirEntry->NameInformation.FileName);
2434
2435             SetFlag( pTargetDirEntry->Flags, AFS_DIR_ENTRY_DELETED);
2436
2437             //
2438             // Try and purge the cache map if this is a file
2439             //
2440
2441             if( pTargetDirEntry->ObjectInformation->FileType == AFS_FILE_TYPE_FILE &&
2442                 pTargetDirEntry->ObjectInformation->Fcb != NULL &&
2443                 pTargetDirEntry->OpenReferenceCount > 1)
2444             {
2445
2446                 pTargetFcb = pTargetDirEntry->ObjectInformation->Fcb;
2447
2448                 AFSAcquireExcl( &pTargetFcb->NPFcb->Resource,
2449                                 TRUE);
2450
2451                 //
2452                 // Close the section in the event it was mapped
2453                 //
2454
2455                 if( !MmForceSectionClosed( &pTargetFcb->NPFcb->SectionObjectPointers,
2456                                            TRUE))
2457                 {
2458
2459                     AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
2460                                   AFS_TRACE_LEVEL_ERROR,
2461                                   "AFSSetRenameInfo Failed to delete section for target file %wZ\n",
2462                                   &pTargetDirEntry->NameInformation.FileName);
2463                 }
2464
2465                 AFSReleaseResource( &pTargetFcb->NPFcb->Resource);
2466             }
2467
2468             ASSERT( pTargetDirEntry->OpenReferenceCount > 0);
2469
2470             InterlockedDecrement( &pTargetDirEntry->OpenReferenceCount); // The count we added above
2471
2472             if( pTargetDirEntry->OpenReferenceCount == 0)
2473             {
2474
2475                 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
2476                               AFS_TRACE_LEVEL_VERBOSE,
2477                               "AFSSetRenameInfo Deleting dir entry %p name %wZ\n",
2478                               pTargetDirEntry,
2479                               &pTargetDirEntry->NameInformation.FileName);
2480
2481                 AFSDeleteDirEntry( pTargetParentObject,
2482                                    pTargetDirEntry);
2483             }
2484
2485             pTargetDirEntry = NULL;
2486         }
2487
2488 try_exit:
2489
2490
2491         if( !NT_SUCCESS( ntStatus))
2492         {
2493
2494             if( bTargetEntryExists)
2495             {
2496                 AFSInsertDirectoryNode( pTargetDirEntry->ObjectInformation->ParentObjectInformation,
2497                                         pTargetDirEntry,
2498                                         FALSE);
2499             }
2500         }
2501
2502         if( pTargetDirEntry != NULL)
2503         {
2504
2505             InterlockedDecrement( &pTargetDirEntry->OpenReferenceCount);
2506         }
2507
2508         if( bReleaseVolumeLock)
2509         {
2510             AFSReleaseResource( pTargetParentObject->VolumeCB->VolumeLock);
2511         }
2512
2513         if( bReleaseTargetDirLock)
2514         {
2515             AFSReleaseResource( pTargetParentObject->Specific.Directory.DirectoryNodeHdr.TreeLock);
2516         }
2517
2518         if( bReleaseSourceDirLock)
2519         {
2520             AFSReleaseResource( pSrcFcb->ObjectInformation->ParentObjectInformation->Specific.Directory.DirectoryNodeHdr.TreeLock);
2521         }
2522     }
2523
2524     return ntStatus;
2525 }
2526
2527 NTSTATUS
2528 AFSSetPositionInfo( IN PIRP Irp,
2529                     IN AFSDirectoryCB *DirectoryCB)
2530 {
2531     NTSTATUS ntStatus = STATUS_SUCCESS;
2532     PFILE_POSITION_INFORMATION pBuffer;
2533     PIO_STACK_LOCATION pIrpSp = IoGetCurrentIrpStackLocation( Irp);
2534
2535     pBuffer = (PFILE_POSITION_INFORMATION)Irp->AssociatedIrp.SystemBuffer;
2536
2537     pIrpSp->FileObject->CurrentByteOffset.QuadPart = pBuffer->CurrentByteOffset.QuadPart;
2538
2539     return ntStatus;
2540 }
2541
2542 NTSTATUS
2543 AFSSetAllocationInfo( IN PIRP Irp,
2544                       IN AFSDirectoryCB *DirectoryCB)
2545 {
2546     NTSTATUS ntStatus = STATUS_SUCCESS;
2547     PFILE_ALLOCATION_INFORMATION pBuffer;
2548     BOOLEAN bReleasePaging = FALSE;
2549     BOOLEAN bTellCc = FALSE;
2550     BOOLEAN bTellService = FALSE;
2551     PIO_STACK_LOCATION pIrpSp = IoGetCurrentIrpStackLocation( Irp);
2552     PFILE_OBJECT pFileObject = pIrpSp->FileObject;
2553     AFSFcb *pFcb = NULL;
2554     AFSCcb *pCcb = NULL;
2555     LARGE_INTEGER liSaveAlloc;
2556     LARGE_INTEGER liSaveFileSize;
2557     LARGE_INTEGER liSaveVDL;
2558
2559     pBuffer = (PFILE_ALLOCATION_INFORMATION)Irp->AssociatedIrp.SystemBuffer;
2560
2561     pFcb = (AFSFcb *)pIrpSp->FileObject->FsContext;
2562
2563     pCcb = (AFSCcb *)pIrpSp->FileObject->FsContext2;
2564
2565     //
2566     // save values to put back
2567     //
2568     liSaveAlloc = pFcb->Header.AllocationSize;
2569     liSaveFileSize = pFcb->Header.FileSize;
2570     liSaveVDL = pFcb->Header.ValidDataLength;
2571
2572     if( pFcb->Header.AllocationSize.QuadPart == pBuffer->AllocationSize.QuadPart ||
2573         pIrpSp->Parameters.SetFile.AdvanceOnly)
2574     {
2575         return STATUS_SUCCESS ;
2576     }
2577
2578     if( pFcb->Header.AllocationSize.QuadPart > pBuffer->AllocationSize.QuadPart)
2579     {
2580         //
2581         // Truncating the file
2582         //
2583         if( !MmCanFileBeTruncated( pFileObject->SectionObjectPointer,
2584                                    &pBuffer->AllocationSize))
2585         {
2586
2587             ntStatus = STATUS_USER_MAPPED_FILE ;
2588         }
2589         else
2590         {
2591             //
2592             // If this is a truncation we need to grab the paging IO resource.
2593             //
2594             AFSDbgLogMsg( AFS_SUBSYSTEM_LOCK_PROCESSING,
2595                           AFS_TRACE_LEVEL_VERBOSE,
2596                           "AFSSetAllocationInfo Acquiring Fcb PagingIo lock %08lX EXCL %08lX\n",
2597                           &pFcb->NPFcb->PagingResource,
2598                           PsGetCurrentThread());
2599
2600             AFSAcquireExcl( &pFcb->NPFcb->PagingResource,
2601                             TRUE);
2602
2603             bReleasePaging = TRUE;
2604
2605
2606             pFcb->Header.AllocationSize = pBuffer->AllocationSize;
2607
2608             pFcb->ObjectInformation->AllocationSize = pBuffer->AllocationSize;
2609
2610             //
2611             // Tell Cc that Allocation is moved.
2612             //
2613             bTellCc = TRUE;
2614
2615             if( pFcb->Header.FileSize.QuadPart > pBuffer->AllocationSize.QuadPart)
2616             {
2617                 //
2618                 // We are pulling the EOF back as well so we need to tell
2619                 // the service.
2620                 //
2621                 bTellService = TRUE;
2622
2623                 pFcb->Header.FileSize = pBuffer->AllocationSize;
2624
2625                 pFcb->ObjectInformation->EndOfFile = pBuffer->AllocationSize;
2626             }
2627
2628         }
2629     }
2630     else
2631     {
2632         //
2633         // Tell Cc if allocation is increased.
2634         //
2635         bTellCc = pBuffer->AllocationSize.QuadPart > pFcb->Header.AllocationSize.QuadPart;
2636
2637         pFcb->Header.AllocationSize = pBuffer->AllocationSize;
2638
2639         pFcb->ObjectInformation->AllocationSize = pBuffer->AllocationSize;
2640     }
2641
2642     //
2643     // Now Tell the server if we have to
2644     //
2645     if (bTellService)
2646     {
2647         ntStatus = AFSUpdateFileInformation( &pFcb->ObjectInformation->ParentObjectInformation->FileId,
2648                                              pFcb->ObjectInformation,
2649                                              &pFcb->AuthGroup);
2650     }
2651
2652     if (NT_SUCCESS(ntStatus))
2653     {
2654         //
2655         // Trim extents if we told the service - the update has done an implicit
2656         // trim at the service.
2657         //
2658         if (bTellService)
2659         {
2660             AFSTrimExtents( pFcb,
2661                             &pFcb->Header.FileSize);
2662         }
2663
2664         KeQuerySystemTime( &pFcb->ObjectInformation->ChangeTime);
2665
2666         SetFlag( pFcb->Flags, AFS_FCB_FLAG_FILE_MODIFIED | AFS_FCB_FLAG_UPDATE_CHANGE_TIME);
2667
2668         if (bTellCc &&
2669             CcIsFileCached( pFileObject))
2670         {
2671             CcSetFileSizes( pFileObject,
2672                             (PCC_FILE_SIZES)&pFcb->Header.AllocationSize);
2673         }
2674     }
2675     else
2676     {
2677         //
2678         // Put the saved values back
2679         //
2680         pFcb->Header.ValidDataLength = liSaveVDL;
2681         pFcb->Header.FileSize = liSaveFileSize;
2682         pFcb->Header.AllocationSize = liSaveAlloc;
2683         pFcb->ObjectInformation->EndOfFile = liSaveFileSize;
2684         pFcb->ObjectInformation->AllocationSize = liSaveAlloc;
2685     }
2686
2687     if( bReleasePaging)
2688     {
2689
2690         AFSReleaseResource( &pFcb->NPFcb->PagingResource);
2691     }
2692
2693     return ntStatus;
2694 }
2695
2696 NTSTATUS
2697 AFSSetEndOfFileInfo( IN PIRP Irp,
2698                      IN AFSDirectoryCB *DirectoryCB)
2699 {
2700     NTSTATUS ntStatus = STATUS_SUCCESS;
2701     PFILE_END_OF_FILE_INFORMATION pBuffer;
2702     PIO_STACK_LOCATION pIrpSp = IoGetCurrentIrpStackLocation( Irp);
2703     PFILE_OBJECT pFileObject = pIrpSp->FileObject;
2704     LARGE_INTEGER liSaveSize;
2705     LARGE_INTEGER liSaveVDL;
2706     LARGE_INTEGER liSaveAlloc;
2707     BOOLEAN bModified = FALSE;
2708     BOOLEAN bReleasePaging = FALSE;
2709     BOOLEAN bTruncated = FALSE;
2710     AFSFcb *pFcb = NULL;
2711     AFSCcb *pCcb = NULL;
2712
2713     pFcb = (AFSFcb *)pIrpSp->FileObject->FsContext;
2714
2715     pCcb = (AFSCcb *)pIrpSp->FileObject->FsContext2;
2716
2717     pBuffer = (PFILE_END_OF_FILE_INFORMATION)Irp->AssociatedIrp.SystemBuffer;
2718
2719     liSaveSize = pFcb->Header.FileSize;
2720     liSaveAlloc = pFcb->Header.AllocationSize;
2721     liSaveVDL = pFcb->Header.ValidDataLength;
2722
2723     if( pFcb->Header.FileSize.QuadPart != pBuffer->EndOfFile.QuadPart &&
2724         !pIrpSp->Parameters.SetFile.AdvanceOnly)
2725     {
2726
2727         if( pBuffer->EndOfFile.QuadPart < pFcb->Header.FileSize.QuadPart)
2728         {
2729
2730             // Truncating the file
2731             if( !MmCanFileBeTruncated( pFileObject->SectionObjectPointer,
2732                                        &pBuffer->EndOfFile))
2733             {
2734
2735                 ntStatus = STATUS_USER_MAPPED_FILE;
2736             }
2737             else
2738             {
2739                 //
2740                 // If this is a truncation we need to grab the paging
2741                 // IO resource.
2742                 //
2743                 AFSDbgLogMsg( AFS_SUBSYSTEM_LOCK_PROCESSING,
2744                               AFS_TRACE_LEVEL_VERBOSE,
2745                               "AFSSetAllocationInfo Acquiring Fcb PagingIo lock %08lX EXCL %08lX\n",
2746                               &pFcb->NPFcb->PagingResource,
2747                               PsGetCurrentThread());
2748
2749                 AFSAcquireExcl( &pFcb->NPFcb->PagingResource,
2750                                 TRUE);
2751
2752                 bReleasePaging = TRUE;
2753
2754                 pFcb->Header.AllocationSize = pBuffer->EndOfFile;
2755
2756                 pFcb->Header.FileSize = pBuffer->EndOfFile;
2757
2758                 pFcb->ObjectInformation->EndOfFile = pBuffer->EndOfFile;
2759
2760                 pFcb->ObjectInformation->AllocationSize = pBuffer->EndOfFile;
2761
2762                 if( pFcb->Header.ValidDataLength.QuadPart > pFcb->Header.FileSize.QuadPart)
2763                 {
2764
2765                     pFcb->Header.ValidDataLength = pFcb->Header.FileSize;
2766                 }
2767
2768                 bTruncated = TRUE;
2769
2770                 bModified = TRUE;
2771             }
2772         }
2773         else
2774         {
2775             //
2776             // extending the file, move EOF
2777             //
2778
2779             pFcb->Header.FileSize = pBuffer->EndOfFile;
2780
2781             pFcb->ObjectInformation->EndOfFile = pBuffer->EndOfFile;
2782
2783             if (pFcb->Header.FileSize.QuadPart > pFcb->Header.AllocationSize.QuadPart)
2784             {
2785                 //
2786                 // And Allocation as needed.
2787                 //
2788                 pFcb->Header.AllocationSize = pBuffer->EndOfFile;
2789
2790                 pFcb->ObjectInformation->AllocationSize = pBuffer->EndOfFile;
2791             }
2792
2793             bModified = TRUE;
2794         }
2795     }
2796
2797     if (bModified)
2798     {
2799
2800         KeQuerySystemTime( &pFcb->ObjectInformation->ChangeTime);
2801
2802         SetFlag( pFcb->Flags, AFS_FCB_FLAG_FILE_MODIFIED | AFS_FCB_FLAG_UPDATE_CHANGE_TIME);
2803
2804         //
2805         // Tell the server
2806         //
2807
2808         ntStatus = AFSUpdateFileInformation( &pFcb->ObjectInformation->ParentObjectInformation->FileId,
2809                                              pFcb->ObjectInformation,
2810                                              &pFcb->AuthGroup);
2811
2812         if( NT_SUCCESS(ntStatus))
2813         {
2814             //
2815             // We are now good to go so tell CC.
2816             //
2817             CcSetFileSizes( pFileObject,
2818                             (PCC_FILE_SIZES)&pFcb->Header.AllocationSize);
2819
2820             //
2821             // And give up those extents
2822             //
2823             if( bTruncated)
2824             {
2825
2826                 AFSTrimExtents( pFcb,
2827                                 &pFcb->Header.FileSize);
2828             }
2829         }
2830         else
2831         {
2832             pFcb->Header.ValidDataLength = liSaveVDL;
2833             pFcb->Header.FileSize = liSaveSize;
2834             pFcb->Header.AllocationSize = liSaveAlloc;
2835             pFcb->ObjectInformation->EndOfFile = liSaveSize;
2836             pFcb->ObjectInformation->AllocationSize = liSaveAlloc;
2837         }
2838     }
2839
2840     if( bReleasePaging)
2841     {
2842
2843         AFSReleaseResource( &pFcb->NPFcb->PagingResource);
2844     }
2845
2846     return ntStatus;
2847 }
2848
2849 NTSTATUS
2850 AFSProcessShareSetInfo( IN IRP *Irp,
2851                         IN AFSFcb *Fcb,
2852                         IN AFSCcb *Ccb)
2853 {
2854
2855     NTSTATUS ntStatus = STATUS_SUCCESS;
2856     PIO_STACK_LOCATION pIrpSp = IoGetCurrentIrpStackLocation( Irp);
2857     ULONG ulOutputBufferLen = 0, ulInputBufferLen;
2858     FILE_INFORMATION_CLASS ulFileInformationClass;
2859     void *pPipeInfo = NULL;
2860
2861     __Enter
2862     {
2863         ulFileInformationClass = pIrpSp->Parameters.SetFile.FileInformationClass;
2864
2865         AFSDbgLogMsg( AFS_SUBSYSTEM_PIPE_PROCESSING,
2866                       AFS_TRACE_LEVEL_VERBOSE,
2867                       "AFSProcessShareSetInfo On pipe %wZ Class %08lX\n",
2868                       &Ccb->DirectoryCB->NameInformation.FileName,
2869                       ulFileInformationClass);
2870
2871         pPipeInfo = AFSLockSystemBuffer( Irp,
2872                                          pIrpSp->Parameters.SetFile.Length);
2873
2874         if( pPipeInfo == NULL)
2875         {
2876
2877             AFSDbgLogMsg( AFS_SUBSYSTEM_PIPE_PROCESSING,
2878                           AFS_TRACE_LEVEL_ERROR,
2879                           "AFSProcessShareSetInfo Failed to lock buffer on pipe %wZ\n",
2880                           &Ccb->DirectoryCB->NameInformation.FileName);
2881
2882             try_return( ntStatus = STATUS_INSUFFICIENT_RESOURCES);
2883         }
2884
2885         //
2886         // Send the request to the service
2887         //
2888
2889         ntStatus = AFSNotifySetPipeInfo( Ccb,
2890                                          (ULONG)ulFileInformationClass,
2891                                          pIrpSp->Parameters.SetFile.Length,
2892                                          pPipeInfo);
2893
2894         if( !NT_SUCCESS( ntStatus))
2895         {
2896
2897             AFSDbgLogMsg( AFS_SUBSYSTEM_PIPE_PROCESSING,
2898                           AFS_TRACE_LEVEL_ERROR,
2899                           "AFSProcessShareSetInfo Failed to send request to service on pipe %wZ Status %08lX\n",
2900                           &Ccb->DirectoryCB->NameInformation.FileName,
2901                           ntStatus);
2902
2903             try_return( ntStatus);
2904         }
2905
2906         AFSDbgLogMsg( AFS_SUBSYSTEM_PIPE_PROCESSING,
2907                       AFS_TRACE_LEVEL_VERBOSE,
2908                       "AFSProcessShareSetInfo Completed request on pipe %wZ Class %08lX\n",
2909                       &Ccb->DirectoryCB->NameInformation.FileName,
2910                       ulFileInformationClass);
2911
2912 try_exit:
2913
2914         NOTHING;
2915     }
2916
2917     return ntStatus;
2918 }
2919
2920 NTSTATUS
2921 AFSProcessShareQueryInfo( IN IRP *Irp,
2922                           IN AFSFcb *Fcb,
2923                           IN AFSCcb *Ccb)
2924 {
2925
2926     NTSTATUS ntStatus = STATUS_SUCCESS;
2927     PIO_STACK_LOCATION pIrpSp = IoGetCurrentIrpStackLocation( Irp);
2928     ULONG ulOutputBufferLen = 0, ulInputBufferLen;
2929     FILE_INFORMATION_CLASS ulFileInformationClass;
2930     void *pPipeInfo = NULL;
2931
2932     __Enter
2933     {
2934
2935         ulFileInformationClass = pIrpSp->Parameters.QueryFile.FileInformationClass;
2936
2937         AFSDbgLogMsg( AFS_SUBSYSTEM_PIPE_PROCESSING,
2938                       AFS_TRACE_LEVEL_VERBOSE,
2939                       "AFSProcessShareQueryInfo On pipe %wZ Class %08lX\n",
2940                       &Ccb->DirectoryCB->NameInformation.FileName,
2941                       ulFileInformationClass);
2942
2943         pPipeInfo = AFSLockSystemBuffer( Irp,
2944                                          pIrpSp->Parameters.QueryFile.Length);
2945
2946         if( pPipeInfo == NULL)
2947         {
2948
2949             AFSDbgLogMsg( AFS_SUBSYSTEM_PIPE_PROCESSING,
2950                           AFS_TRACE_LEVEL_ERROR,
2951                           "AFSProcessShareQueryInfo Failed to lock buffer on pipe %wZ\n",
2952                           &Ccb->DirectoryCB->NameInformation.FileName);
2953
2954             try_return( ntStatus = STATUS_INSUFFICIENT_RESOURCES);
2955         }
2956
2957         //
2958         // Send the request to the service
2959         //
2960
2961         ntStatus = AFSNotifyQueryPipeInfo( Ccb,
2962                                            (ULONG)ulFileInformationClass,
2963                                            pIrpSp->Parameters.QueryFile.Length,
2964                                            pPipeInfo,
2965                                            (ULONG *)&Irp->IoStatus.Information);
2966
2967         if( !NT_SUCCESS( ntStatus))
2968         {
2969
2970             AFSDbgLogMsg( AFS_SUBSYSTEM_PIPE_PROCESSING,
2971                           AFS_TRACE_LEVEL_ERROR,
2972                           "AFSProcessShareQueryInfo Failed to send request to service on pipe %wZ Status %08lX\n",
2973                           &Ccb->DirectoryCB->NameInformation.FileName,
2974                           ntStatus);
2975
2976             try_return( ntStatus);
2977         }
2978
2979         AFSDbgLogMsg( AFS_SUBSYSTEM_PIPE_PROCESSING,
2980                       AFS_TRACE_LEVEL_VERBOSE,
2981                       "AFSProcessShareQueryInfo Completed request on pipe %wZ Class %08lX\n",
2982                       &Ccb->DirectoryCB->NameInformation.FileName,
2983                       ulFileInformationClass);
2984
2985 try_exit:
2986
2987         NOTHING;
2988     }
2989
2990     return ntStatus;
2991 }
2992
2993 NTSTATUS
2994 AFSProcessPIOCtlQueryInfo( IN IRP *Irp,
2995                            IN AFSFcb *Fcb,
2996                            IN AFSCcb *Ccb,
2997                            IN OUT LONG *Length)
2998 {
2999
3000     NTSTATUS ntStatus = STATUS_SUCCESS;
3001     PIO_STACK_LOCATION pIrpSp = IoGetCurrentIrpStackLocation( Irp);
3002     FILE_INFORMATION_CLASS ulFileInformationClass;
3003
3004     __Enter
3005     {
3006
3007         ulFileInformationClass = pIrpSp->Parameters.QueryFile.FileInformationClass;
3008
3009         switch( ulFileInformationClass)
3010         {
3011
3012             case FileBasicInformation:
3013             {
3014
3015                 if ( *Length >= sizeof( FILE_BASIC_INFORMATION))
3016                 {
3017                     PFILE_BASIC_INFORMATION pBasic = (PFILE_BASIC_INFORMATION)Irp->AssociatedIrp.SystemBuffer;
3018
3019                     pBasic->CreationTime.QuadPart = 0;
3020                     pBasic->LastAccessTime.QuadPart = 0;
3021                     pBasic->ChangeTime.QuadPart = 0;
3022                     pBasic->LastWriteTime.QuadPart = 0;
3023                     pBasic->FileAttributes = FILE_ATTRIBUTE_SYSTEM;
3024
3025                     *Length -= sizeof( FILE_BASIC_INFORMATION);
3026                 }
3027                 else
3028                 {
3029                     ntStatus = STATUS_BUFFER_OVERFLOW;
3030                 }
3031
3032                 break;
3033             }
3034
3035             case FileStandardInformation:
3036             {
3037
3038                 if ( *Length >= sizeof( FILE_STANDARD_INFORMATION))
3039                 {
3040                     PFILE_STANDARD_INFORMATION pStandard = (PFILE_STANDARD_INFORMATION)Irp->AssociatedIrp.SystemBuffer;
3041
3042                     pStandard->NumberOfLinks = 1;
3043                     pStandard->DeletePending = 0;
3044                     pStandard->AllocationSize.QuadPart = 4096;
3045                     pStandard->EndOfFile.QuadPart = 4096;
3046                     pStandard->Directory = 0;
3047
3048                     *Length -= sizeof( FILE_STANDARD_INFORMATION);
3049                 }
3050                 else
3051                 {
3052                     ntStatus = STATUS_BUFFER_OVERFLOW;
3053                 }
3054
3055                 break;
3056             }
3057
3058             case FileNameInformation:
3059             {
3060
3061                 ULONG ulCopyLength = 0;
3062                 AFSFcb *pFcb = NULL;
3063                 AFSCcb *pCcb = NULL;
3064                 USHORT usFullNameLength = 0;
3065                 PFILE_NAME_INFORMATION pNameInfo = (PFILE_NAME_INFORMATION)Irp->AssociatedIrp.SystemBuffer;
3066                 UNICODE_STRING uniName;
3067
3068                 pFcb = (AFSFcb *)pIrpSp->FileObject->FsContext;
3069                 pCcb = (AFSCcb *)pIrpSp->FileObject->FsContext2;
3070
3071                 if( *Length < FIELD_OFFSET( FILE_NAME_INFORMATION, FileName))
3072                 {
3073                     ntStatus = STATUS_BUFFER_TOO_SMALL;
3074                     break;
3075                 }
3076
3077                 RtlZeroMemory( pNameInfo,
3078                                *Length);
3079
3080                 usFullNameLength = sizeof( WCHAR) +
3081                                             AFSServerName.Length +
3082                                             pCcb->FullFileName.Length;
3083
3084                 if( *Length >= (LONG)(FIELD_OFFSET( FILE_NAME_INFORMATION, FileName) + (LONG)usFullNameLength))
3085                 {
3086                     ulCopyLength = (LONG)usFullNameLength;
3087                 }
3088                 else
3089                 {
3090                     ulCopyLength = *Length - FIELD_OFFSET( FILE_NAME_INFORMATION, FileName);
3091                     ntStatus = STATUS_BUFFER_OVERFLOW;
3092                 }
3093
3094                 pNameInfo->FileNameLength = (ULONG)usFullNameLength;
3095
3096                 *Length -= FIELD_OFFSET( FILE_NAME_INFORMATION, FileName);
3097
3098                 if( ulCopyLength > 0)
3099                 {
3100
3101                     pNameInfo->FileName[ 0] = L'\\';
3102                     ulCopyLength -= sizeof( WCHAR);
3103
3104                     *Length -= sizeof( WCHAR);
3105
3106                     if( ulCopyLength >= AFSServerName.Length)
3107                     {
3108
3109                         RtlCopyMemory( &pNameInfo->FileName[ 1],
3110                                        AFSServerName.Buffer,
3111                                        AFSServerName.Length);
3112
3113                         ulCopyLength -= AFSServerName.Length;
3114                         *Length -= AFSServerName.Length;
3115
3116                         if( ulCopyLength >= pCcb->FullFileName.Length)
3117                         {
3118
3119                             RtlCopyMemory( &pNameInfo->FileName[ 1 + (AFSServerName.Length/sizeof( WCHAR))],
3120                                            pCcb->FullFileName.Buffer,
3121                                            pCcb->FullFileName.Length);
3122
3123                             ulCopyLength -= pCcb->FullFileName.Length;
3124                             *Length -= pCcb->FullFileName.Length;
3125
3126                             uniName.Length = (USHORT)pNameInfo->FileNameLength;
3127                             uniName.MaximumLength = uniName.Length;
3128                             uniName.Buffer = pNameInfo->FileName;
3129                         }
3130                         else
3131                         {
3132
3133                             RtlCopyMemory( &pNameInfo->FileName[ 1 + (AFSServerName.Length/sizeof( WCHAR))],
3134                                            pCcb->FullFileName.Buffer,
3135                                            ulCopyLength);
3136
3137                             *Length -= ulCopyLength;
3138
3139                             uniName.Length = (USHORT)(sizeof( WCHAR) + AFSServerName.Length + ulCopyLength);
3140                             uniName.MaximumLength = uniName.Length;
3141                             uniName.Buffer = pNameInfo->FileName;
3142                         }
3143
3144                         AFSDbgLogMsg( AFS_SUBSYSTEM_PIOCTL_PROCESSING,
3145                                       AFS_TRACE_LEVEL_VERBOSE,
3146                                       "AFSProcessPIOCtlQueryInfo (FileNameInformation) Returning %wZ\n",
3147                                       &uniName);
3148                     }
3149                 }
3150
3151                 break;
3152             }
3153
3154             case FileInternalInformation:
3155             {
3156
3157                 PFILE_INTERNAL_INFORMATION pInternalInfo = (PFILE_INTERNAL_INFORMATION)Irp->AssociatedIrp.SystemBuffer;
3158
3159                 if( *Length >= sizeof( FILE_INTERNAL_INFORMATION))
3160                 {
3161
3162                     pInternalInfo->IndexNumber.HighPart = 0;
3163
3164                     pInternalInfo->IndexNumber.LowPart = 0;
3165
3166                     *Length -= sizeof( FILE_INTERNAL_INFORMATION);
3167                 }
3168                 else
3169                 {
3170
3171                     ntStatus = STATUS_BUFFER_TOO_SMALL;
3172                 }
3173
3174                 break;
3175             }
3176
3177             default:
3178             {
3179                 ntStatus = STATUS_INVALID_PARAMETER;
3180
3181                 AFSDbgLogMsg( AFS_SUBSYSTEM_PIOCTL_PROCESSING,
3182                               AFS_TRACE_LEVEL_WARNING,
3183                               "AFSProcessPIOCtlQueryInfo Not handling request %08lX\n",
3184                               ulFileInformationClass);
3185
3186                 break;
3187             }
3188         }
3189     }
3190
3191     return ntStatus;
3192 }
3193