Windows: Failed to release correct lock
[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     PERESOURCE  pSourceDirLock = NULL;
1921
1922     __Enter
1923     {
1924
1925         bReplaceIfExists = pIrpSp->Parameters.SetFile.ReplaceIfExists;
1926
1927         pSrcFcb = (AFSFcb *)pSrcFileObj->FsContext;
1928         pSrcCcb = (AFSCcb *)pSrcFileObj->FsContext2;
1929
1930         pSrcObject = pSrcFcb->ObjectInformation;
1931
1932         //
1933         // Perform some basic checks to ensure FS integrity
1934         //
1935
1936         if( pSrcFcb->Header.NodeTypeCode == AFS_ROOT_FCB)
1937         {
1938
1939             //
1940             // Can't rename the root directory
1941             //
1942
1943             AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
1944                           AFS_TRACE_LEVEL_ERROR,
1945                           "AFSSetRenameInfo Attempt to rename root entry\n");
1946
1947             try_return( ntStatus = STATUS_INVALID_PARAMETER);
1948         }
1949
1950         if( pSrcFcb->Header.NodeTypeCode == AFS_DIRECTORY_FCB)
1951         {
1952
1953             //
1954             // If there are any open children then fail the rename
1955             //
1956
1957             if( pSrcFcb->ObjectInformation->Specific.Directory.ChildOpenHandleCount > 0)
1958             {
1959
1960                 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
1961                               AFS_TRACE_LEVEL_ERROR,
1962                               "AFSSetRenameInfo Attempt to rename directory with open children %wZ\n",
1963                               &pSrcCcb->DirectoryCB->NameInformation.FileName);
1964
1965                 try_return( ntStatus = STATUS_ACCESS_DENIED);
1966             }
1967         }
1968         else
1969         {
1970
1971             if( pSrcFcb->OpenHandleCount > 1)
1972             {
1973
1974                 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
1975                               AFS_TRACE_LEVEL_ERROR,
1976                               "AFSSetRenameInfo Attempt to rename directory with open references %wZ\n",
1977                               &pSrcCcb->DirectoryCB->NameInformation.FileName);
1978
1979                 try_return( ntStatus = STATUS_ACCESS_DENIED);
1980             }
1981         }
1982
1983         //
1984         // Resolve the target fileobject
1985         //
1986
1987         if( pTargetFileObj == NULL)
1988         {
1989
1990             //
1991             // This is a simple rename. Here the target directory is the same as the source parent directory
1992             // and the name is retrieved from the system buffer information
1993             //
1994
1995             pRenameInfo = (PFILE_RENAME_INFORMATION)Irp->AssociatedIrp.SystemBuffer;
1996
1997             pTargetParentObject = pSrcFcb->ObjectInformation->ParentObjectInformation;
1998
1999             pTargetDcb = pTargetParentObject->Fcb;
2000
2001             uniTargetName.Length = (USHORT)pRenameInfo->FileNameLength;
2002             uniTargetName.Buffer = (PWSTR)&pRenameInfo->FileName;
2003         }
2004         else
2005         {
2006
2007             //
2008             // So here we have the target directory taken from the targetfile object
2009             //
2010
2011             pTargetDcb = (AFSFcb *)pTargetFileObj->FsContext;
2012
2013             pTargetDirCcb = (AFSCcb *)pTargetFileObj->FsContext2;
2014
2015             pTargetParentObject = (AFSObjectInfoCB *)pTargetDcb->ObjectInformation;
2016
2017             //
2018             // Grab the target name which we setup in the IRP_MJ_CREATE handler. By how we set this up
2019             // it is only the target component of the rename operation
2020             //
2021
2022             uniTargetName = *((PUNICODE_STRING)&pTargetFileObj->FileName);
2023         }
2024
2025         //
2026         // We do not allow cross-volume renames to occur
2027         //
2028
2029         if( pTargetParentObject->VolumeCB != pSrcObject->VolumeCB)
2030         {
2031
2032             AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
2033                           AFS_TRACE_LEVEL_ERROR,
2034                           "AFSSetRenameInfo Attempt to rename directory to different volume %wZ\n",
2035                           &pSrcCcb->DirectoryCB->NameInformation.FileName);
2036
2037             try_return( ntStatus = STATUS_NOT_SAME_DEVICE);
2038         }
2039
2040         AFSAcquireExcl( pTargetParentObject->VolumeCB->VolumeLock,
2041                         TRUE);
2042
2043         bReleaseVolumeLock = TRUE;
2044
2045         ulTargetCRC = AFSGenerateCRC( &uniTargetName,
2046                                       FALSE);
2047
2048         AFSAcquireExcl( pTargetParentObject->Specific.Directory.DirectoryNodeHdr.TreeLock,
2049                         TRUE);
2050
2051         bReleaseTargetDirLock = TRUE;
2052
2053         if( pTargetParentObject != pSrcFcb->ObjectInformation->ParentObjectInformation)
2054         {
2055             AFSAcquireExcl( pSrcFcb->ObjectInformation->ParentObjectInformation->Specific.Directory.DirectoryNodeHdr.TreeLock,
2056                             TRUE);
2057
2058             bReleaseSourceDirLock = TRUE;
2059
2060             pSourceDirLock = pSrcFcb->ObjectInformation->ParentObjectInformation->Specific.Directory.DirectoryNodeHdr.TreeLock;
2061         }
2062
2063         AFSLocateCaseSensitiveDirEntry( pTargetParentObject->Specific.Directory.DirectoryNodeHdr.CaseSensitiveTreeHead,
2064                                         ulTargetCRC,
2065                                         &pTargetDirEntry);
2066
2067         if( pTargetDirEntry == NULL)
2068         {
2069
2070             //
2071             // Missed so perform a case insensitive lookup
2072             //
2073
2074             ulTargetCRC = AFSGenerateCRC( &uniTargetName,
2075                                           TRUE);
2076
2077             AFSLocateCaseInsensitiveDirEntry( pTargetParentObject->Specific.Directory.DirectoryNodeHdr.CaseInsensitiveTreeHead,
2078                                               ulTargetCRC,
2079                                               &pTargetDirEntry);
2080         }
2081
2082         if( pTargetDirEntry == NULL && RtlIsNameLegalDOS8Dot3( &uniTargetName,
2083                                                                NULL,
2084                                                                NULL))
2085         {
2086             //
2087             // Try the short name
2088             //
2089             AFSLocateShortNameDirEntry( pTargetParentObject->Specific.Directory.ShortNameTree,
2090                                         ulTargetCRC,
2091                                         &pTargetDirEntry);
2092         }
2093
2094         //
2095         // Increment our ref count on the dir entry
2096         //
2097
2098         if( pTargetDirEntry != NULL)
2099         {
2100
2101             ASSERT( pTargetParentObject == pTargetDirEntry->ObjectInformation->ParentObjectInformation);
2102
2103             InterlockedIncrement( &pTargetDirEntry->OpenReferenceCount);
2104
2105             if( !bReplaceIfExists)
2106             {
2107
2108                 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
2109                               AFS_TRACE_LEVEL_ERROR,
2110                               "AFSSetRenameInfo Attempt to rename directory with target collision %wZ Target %wZ\n",
2111                               &pSrcCcb->DirectoryCB->NameInformation.FileName,
2112                               &pTargetDirEntry->NameInformation.FileName);
2113
2114                 try_return( ntStatus = STATUS_OBJECT_NAME_COLLISION);
2115             }
2116
2117             AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
2118                           AFS_TRACE_LEVEL_ERROR,
2119                           "AFSSetRenameInfo Target %wZ exists DE %p Count %08lX, performing delete of target\n",
2120                           &pTargetDirEntry->NameInformation.FileName,
2121                           pTargetDirEntry,
2122                           pTargetDirEntry->OpenReferenceCount);
2123
2124             //
2125             // Pull the directory entry from the parent
2126             //
2127
2128             AFSRemoveDirNodeFromParent( pTargetParentObject,
2129                                         pTargetDirEntry,
2130                                         FALSE);
2131
2132             bTargetEntryExists = TRUE;
2133         }
2134         else
2135         {
2136             AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
2137                           AFS_TRACE_LEVEL_ERROR,
2138                           "AFSSetRenameInfo Target Target does NOT exist, normal rename\n");
2139         }
2140
2141         //
2142         // Extract off the final component name from the Fcb
2143         //
2144
2145         uniSourceName.Length = (USHORT)pSrcCcb->DirectoryCB->NameInformation.FileName.Length;
2146         uniSourceName.MaximumLength = uniSourceName.Length;
2147
2148         uniSourceName.Buffer = pSrcCcb->DirectoryCB->NameInformation.FileName.Buffer;
2149
2150         //
2151         // The quick check to see if they are not really performing a rename
2152         // Do the names match? Only do this where the parent directories are
2153         // the same
2154         //
2155
2156         if( pTargetParentObject == pSrcFcb->ObjectInformation->ParentObjectInformation)
2157         {
2158
2159             bCommonParent = TRUE;
2160
2161             if( FsRtlAreNamesEqual( &uniTargetName,
2162                                     &uniSourceName,
2163                                     FALSE,
2164                                     NULL))
2165             {
2166                 try_return( ntStatus = STATUS_SUCCESS);
2167             }
2168         }
2169         else
2170         {
2171
2172             bCommonParent = FALSE;
2173         }
2174
2175         //
2176         // We need to remove the DirEntry from the parent node, update the index
2177         // and reinsert it into the parent tree. Note that for entries with the
2178         // same parent we do not pull the node from the enumeration list
2179         //
2180
2181         AFSRemoveDirNodeFromParent( pSrcFcb->ObjectInformation->ParentObjectInformation,
2182                                     pSrcCcb->DirectoryCB,
2183                                     !bCommonParent);
2184
2185         oldFileIndex = pSrcCcb->DirectoryCB->FileIndex;
2186
2187         if( !bCommonParent)
2188         {
2189
2190             //
2191             // We always need to update the FileIndex since this entry will be put at the 'end'
2192             // of the enumeraiton list. If we don't it will cause recursion ... We do this
2193             // here to cover any failures which might occur below
2194             //
2195
2196             pSrcCcb->DirectoryCB->FileIndex =
2197                             (ULONG)InterlockedIncrement( &pTargetDcb->ObjectInformation->ParentObjectInformation->Specific.Directory.DirectoryNodeHdr.ContentIndex);
2198         }
2199
2200         //
2201         // OK, this is a simple rename. Issue the rename
2202         // request to the service.
2203         //
2204
2205         ntStatus = AFSNotifyRename( pSrcFcb->ObjectInformation,
2206                                     pSrcFcb->ObjectInformation->ParentObjectInformation,
2207                                     pTargetDcb->ObjectInformation,
2208                                     pSrcCcb->DirectoryCB,
2209                                     &uniTargetName,
2210                                     &stNewFid);
2211
2212         if( !NT_SUCCESS( ntStatus))
2213         {
2214
2215             //
2216             // Attempt to re-insert the directory entry
2217             //
2218
2219             pSrcCcb->DirectoryCB->FileIndex = oldFileIndex;
2220             AFSInsertDirectoryNode( pSrcFcb->ObjectInformation->ParentObjectInformation,
2221                                     pSrcCcb->DirectoryCB,
2222                                     !bCommonParent);
2223
2224             AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
2225                           AFS_TRACE_LEVEL_ERROR,
2226                           "AFSSetRenameInfo Failed rename of %wZ to target %wZ Status %08lX\n",
2227                           &pSrcCcb->DirectoryCB->NameInformation.FileName,
2228                           &uniTargetName,
2229                           ntStatus);
2230
2231             try_return( ntStatus);
2232         }
2233
2234         //
2235         // Set the notification up for the source file
2236         //
2237
2238         if( pSrcCcb->DirectoryCB->ObjectInformation->ParentObjectInformation == pTargetParentObject &&
2239             !bTargetEntryExists)
2240         {
2241
2242             ulNotificationAction = FILE_ACTION_RENAMED_OLD_NAME;
2243         }
2244         else
2245         {
2246
2247             ulNotificationAction = FILE_ACTION_REMOVED;
2248         }
2249
2250         if( pSrcCcb->DirectoryCB->ObjectInformation->FileType == AFS_FILE_TYPE_DIRECTORY)
2251         {
2252
2253             ulNotifyFilter = FILE_NOTIFY_CHANGE_DIR_NAME;
2254         }
2255         else
2256         {
2257
2258             ulNotifyFilter = FILE_NOTIFY_CHANGE_FILE_NAME;
2259         }
2260
2261         AFSFsRtlNotifyFullReportChange( pSrcCcb->DirectoryCB->ObjectInformation->ParentObjectInformation,
2262                                         pSrcCcb,
2263                                         (ULONG)ulNotifyFilter,
2264                                         (ULONG)ulNotificationAction);
2265
2266         //
2267         // Update the name in the dir entry.
2268         //
2269
2270         ntStatus = AFSUpdateDirEntryName( pSrcCcb->DirectoryCB,
2271                                           &uniTargetName);
2272
2273         if( !NT_SUCCESS( ntStatus))
2274         {
2275
2276             //
2277             // Attempt to re-insert the directory entry
2278             //
2279
2280             pSrcCcb->DirectoryCB->FileIndex = oldFileIndex;
2281             AFSInsertDirectoryNode( pSrcFcb->ObjectInformation->ParentObjectInformation,
2282                                     pSrcCcb->DirectoryCB,
2283                                     !bCommonParent);
2284
2285             AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
2286                           AFS_TRACE_LEVEL_ERROR,
2287                           "AFSSetRenameInfo Failed update of dir entry %wZ to target %wZ Status %08lX\n",
2288                           &pSrcCcb->DirectoryCB->NameInformation.FileName,
2289                           &uniTargetName,
2290                           ntStatus);
2291
2292             try_return( ntStatus);
2293         }
2294
2295         //
2296         // Update the object information block, if needed
2297         //
2298
2299         if( !AFSIsEqualFID( &pSrcObject->FileId,
2300                             &stNewFid))
2301         {
2302
2303             //
2304             // Remove the old information entry
2305             //
2306
2307             AFSRemoveHashEntry( &pSrcObject->VolumeCB->ObjectInfoTree.TreeHead,
2308                                 &pSrcObject->TreeEntry);
2309
2310             RtlCopyMemory( &pSrcObject->FileId,
2311                            &stNewFid,
2312                            sizeof( AFSFileID));
2313
2314             //
2315             // Insert the entry into the new object table.
2316             //
2317
2318             pSrcObject->TreeEntry.HashIndex = AFSCreateLowIndex( &pSrcObject->FileId);
2319
2320             if( pSrcObject->VolumeCB->ObjectInfoTree.TreeHead == NULL)
2321             {
2322
2323                 pSrcObject->VolumeCB->ObjectInfoTree.TreeHead = &pSrcObject->TreeEntry;
2324             }
2325             else
2326             {
2327
2328                 AFSInsertHashEntry( pSrcObject->VolumeCB->ObjectInfoTree.TreeHead,
2329                                     &pSrcObject->TreeEntry);
2330             }
2331         }
2332
2333         //
2334         // Update the hash values for the name trees.
2335         //
2336
2337         pSrcCcb->DirectoryCB->CaseSensitiveTreeEntry.HashIndex = AFSGenerateCRC( &pSrcCcb->DirectoryCB->NameInformation.FileName,
2338                                                                                  FALSE);
2339
2340         pSrcCcb->DirectoryCB->CaseInsensitiveTreeEntry.HashIndex = AFSGenerateCRC( &pSrcCcb->DirectoryCB->NameInformation.FileName,
2341                                                                                    TRUE);
2342
2343         if( pSrcCcb->DirectoryCB->NameInformation.ShortNameLength > 0 &&
2344             !RtlIsNameLegalDOS8Dot3( &pSrcCcb->DirectoryCB->NameInformation.FileName,
2345                                      NULL,
2346                                      NULL))
2347         {
2348
2349             uniShortName.Length = pSrcCcb->DirectoryCB->NameInformation.ShortNameLength;
2350             uniShortName.MaximumLength = uniShortName.Length;
2351             uniShortName.Buffer = pSrcCcb->DirectoryCB->NameInformation.ShortName;
2352
2353             pSrcCcb->DirectoryCB->Type.Data.ShortNameTreeEntry.HashIndex = AFSGenerateCRC( &uniShortName,
2354                                                                                            TRUE);
2355
2356             AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
2357                           AFS_TRACE_LEVEL_VERBOSE,
2358                           "AFSSetRenameInfo Initialized short name hash for %wZ longname %wZ\n",
2359                           &uniShortName,
2360                           &pSrcCcb->DirectoryCB->NameInformation.FileName);
2361         }
2362         else
2363         {
2364
2365             pSrcCcb->DirectoryCB->Type.Data.ShortNameTreeEntry.HashIndex = 0;
2366         }
2367
2368         if( !bCommonParent)
2369         {
2370
2371             //
2372             // Update the file index for the object in the new parent
2373             //
2374
2375             pSrcCcb->DirectoryCB->FileIndex = (ULONG)InterlockedIncrement( &pTargetParentObject->Specific.Directory.DirectoryNodeHdr.ContentIndex);
2376         }
2377
2378         //
2379         // Re-insert the directory entry
2380         //
2381
2382         AFSInsertDirectoryNode( pTargetParentObject,
2383                                 pSrcCcb->DirectoryCB,
2384                                 !bCommonParent);
2385
2386         //
2387         // Update the parent pointer in the source object if they are different
2388         //
2389
2390         if( pSrcCcb->DirectoryCB->ObjectInformation->ParentObjectInformation != pTargetParentObject)
2391         {
2392
2393             InterlockedDecrement( &pSrcCcb->DirectoryCB->ObjectInformation->ParentObjectInformation->Specific.Directory.ChildOpenHandleCount);
2394
2395             InterlockedDecrement( &pSrcCcb->DirectoryCB->ObjectInformation->ParentObjectInformation->Specific.Directory.ChildOpenReferenceCount);
2396
2397             InterlockedIncrement( &pTargetParentObject->Specific.Directory.ChildOpenHandleCount);
2398
2399             InterlockedIncrement( &pTargetParentObject->Specific.Directory.ChildOpenReferenceCount);
2400
2401             pSrcCcb->DirectoryCB->ObjectInformation->ParentObjectInformation = pTargetParentObject;
2402
2403             ulNotificationAction = FILE_ACTION_ADDED;
2404         }
2405         else
2406         {
2407
2408             ulNotificationAction = FILE_ACTION_RENAMED_NEW_NAME;
2409         }
2410
2411         //
2412         // Now update the notification for the target file
2413         //
2414
2415         AFSFsRtlNotifyFullReportChange( pTargetParentObject->ParentObjectInformation,
2416                                         pSrcCcb,
2417                                         (ULONG)ulNotifyFilter,
2418                                         (ULONG)ulNotificationAction);
2419
2420         //
2421         // If we performed the rename of the target because it existed, we now need to
2422         // delete the tmp target we created above
2423         //
2424
2425         if( bTargetEntryExists)
2426         {
2427
2428             AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
2429                           AFS_TRACE_LEVEL_VERBOSE,
2430                           "AFSSetRenameInfo Setting DELETE flag in dir entry %p name %wZ\n",
2431                           pTargetDirEntry,
2432                           &pTargetDirEntry->NameInformation.FileName);
2433
2434             SetFlag( pTargetDirEntry->Flags, AFS_DIR_ENTRY_DELETED);
2435
2436             //
2437             // Try and purge the cache map if this is a file
2438             //
2439
2440             if( pTargetDirEntry->ObjectInformation->FileType == AFS_FILE_TYPE_FILE &&
2441                 pTargetDirEntry->ObjectInformation->Fcb != NULL &&
2442                 pTargetDirEntry->OpenReferenceCount > 1)
2443             {
2444
2445                 pTargetFcb = pTargetDirEntry->ObjectInformation->Fcb;
2446
2447                 AFSAcquireExcl( &pTargetFcb->NPFcb->Resource,
2448                                 TRUE);
2449
2450                 //
2451                 // Close the section in the event it was mapped
2452                 //
2453
2454                 if( !MmForceSectionClosed( &pTargetFcb->NPFcb->SectionObjectPointers,
2455                                            TRUE))
2456                 {
2457
2458                     AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
2459                                   AFS_TRACE_LEVEL_ERROR,
2460                                   "AFSSetRenameInfo Failed to delete section for target file %wZ\n",
2461                                   &pTargetDirEntry->NameInformation.FileName);
2462                 }
2463
2464                 AFSReleaseResource( &pTargetFcb->NPFcb->Resource);
2465             }
2466
2467             ASSERT( pTargetDirEntry->OpenReferenceCount > 0);
2468
2469             InterlockedDecrement( &pTargetDirEntry->OpenReferenceCount); // The count we added above
2470
2471             if( pTargetDirEntry->OpenReferenceCount == 0)
2472             {
2473
2474                 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
2475                               AFS_TRACE_LEVEL_VERBOSE,
2476                               "AFSSetRenameInfo Deleting dir entry %p name %wZ\n",
2477                               pTargetDirEntry,
2478                               &pTargetDirEntry->NameInformation.FileName);
2479
2480                 AFSDeleteDirEntry( pTargetParentObject,
2481                                    pTargetDirEntry);
2482             }
2483
2484             pTargetDirEntry = NULL;
2485         }
2486
2487 try_exit:
2488
2489
2490         if( !NT_SUCCESS( ntStatus))
2491         {
2492
2493             if( bTargetEntryExists)
2494             {
2495                 AFSInsertDirectoryNode( pTargetDirEntry->ObjectInformation->ParentObjectInformation,
2496                                         pTargetDirEntry,
2497                                         FALSE);
2498             }
2499         }
2500
2501         if( pTargetDirEntry != NULL)
2502         {
2503
2504             InterlockedDecrement( &pTargetDirEntry->OpenReferenceCount);
2505         }
2506
2507         if( bReleaseVolumeLock)
2508         {
2509             AFSReleaseResource( pTargetParentObject->VolumeCB->VolumeLock);
2510         }
2511
2512         if( bReleaseTargetDirLock)
2513         {
2514             AFSReleaseResource( pTargetParentObject->Specific.Directory.DirectoryNodeHdr.TreeLock);
2515         }
2516
2517         if( bReleaseSourceDirLock)
2518         {
2519             AFSReleaseResource( pSourceDirLock);
2520         }
2521     }
2522
2523     return ntStatus;
2524 }
2525
2526 NTSTATUS
2527 AFSSetPositionInfo( IN PIRP Irp,
2528                     IN AFSDirectoryCB *DirectoryCB)
2529 {
2530     NTSTATUS ntStatus = STATUS_SUCCESS;
2531     PFILE_POSITION_INFORMATION pBuffer;
2532     PIO_STACK_LOCATION pIrpSp = IoGetCurrentIrpStackLocation( Irp);
2533
2534     pBuffer = (PFILE_POSITION_INFORMATION)Irp->AssociatedIrp.SystemBuffer;
2535
2536     pIrpSp->FileObject->CurrentByteOffset.QuadPart = pBuffer->CurrentByteOffset.QuadPart;
2537
2538     return ntStatus;
2539 }
2540
2541 NTSTATUS
2542 AFSSetAllocationInfo( IN PIRP Irp,
2543                       IN AFSDirectoryCB *DirectoryCB)
2544 {
2545     NTSTATUS ntStatus = STATUS_SUCCESS;
2546     PFILE_ALLOCATION_INFORMATION pBuffer;
2547     BOOLEAN bReleasePaging = FALSE;
2548     BOOLEAN bTellCc = FALSE;
2549     BOOLEAN bTellService = FALSE;
2550     PIO_STACK_LOCATION pIrpSp = IoGetCurrentIrpStackLocation( Irp);
2551     PFILE_OBJECT pFileObject = pIrpSp->FileObject;
2552     AFSFcb *pFcb = NULL;
2553     AFSCcb *pCcb = NULL;
2554     LARGE_INTEGER liSaveAlloc;
2555     LARGE_INTEGER liSaveFileSize;
2556     LARGE_INTEGER liSaveVDL;
2557
2558     pBuffer = (PFILE_ALLOCATION_INFORMATION)Irp->AssociatedIrp.SystemBuffer;
2559
2560     pFcb = (AFSFcb *)pIrpSp->FileObject->FsContext;
2561
2562     pCcb = (AFSCcb *)pIrpSp->FileObject->FsContext2;
2563
2564     //
2565     // save values to put back
2566     //
2567     liSaveAlloc = pFcb->Header.AllocationSize;
2568     liSaveFileSize = pFcb->Header.FileSize;
2569     liSaveVDL = pFcb->Header.ValidDataLength;
2570
2571     if( pFcb->Header.AllocationSize.QuadPart == pBuffer->AllocationSize.QuadPart ||
2572         pIrpSp->Parameters.SetFile.AdvanceOnly)
2573     {
2574         return STATUS_SUCCESS ;
2575     }
2576
2577     if( pFcb->Header.AllocationSize.QuadPart > pBuffer->AllocationSize.QuadPart)
2578     {
2579         //
2580         // Truncating the file
2581         //
2582         if( !MmCanFileBeTruncated( pFileObject->SectionObjectPointer,
2583                                    &pBuffer->AllocationSize))
2584         {
2585
2586             ntStatus = STATUS_USER_MAPPED_FILE ;
2587         }
2588         else
2589         {
2590             //
2591             // If this is a truncation we need to grab the paging IO resource.
2592             //
2593             AFSDbgLogMsg( AFS_SUBSYSTEM_LOCK_PROCESSING,
2594                           AFS_TRACE_LEVEL_VERBOSE,
2595                           "AFSSetAllocationInfo Acquiring Fcb PagingIo lock %08lX EXCL %08lX\n",
2596                           &pFcb->NPFcb->PagingResource,
2597                           PsGetCurrentThread());
2598
2599             AFSAcquireExcl( &pFcb->NPFcb->PagingResource,
2600                             TRUE);
2601
2602             bReleasePaging = TRUE;
2603
2604
2605             pFcb->Header.AllocationSize = pBuffer->AllocationSize;
2606
2607             pFcb->ObjectInformation->AllocationSize = pBuffer->AllocationSize;
2608
2609             //
2610             // Tell Cc that Allocation is moved.
2611             //
2612             bTellCc = TRUE;
2613
2614             if( pFcb->Header.FileSize.QuadPart > pBuffer->AllocationSize.QuadPart)
2615             {
2616                 //
2617                 // We are pulling the EOF back as well so we need to tell
2618                 // the service.
2619                 //
2620                 bTellService = TRUE;
2621
2622                 pFcb->Header.FileSize = pBuffer->AllocationSize;
2623
2624                 pFcb->ObjectInformation->EndOfFile = pBuffer->AllocationSize;
2625             }
2626
2627         }
2628     }
2629     else
2630     {
2631         //
2632         // Tell Cc if allocation is increased.
2633         //
2634         bTellCc = pBuffer->AllocationSize.QuadPart > pFcb->Header.AllocationSize.QuadPart;
2635
2636         pFcb->Header.AllocationSize = pBuffer->AllocationSize;
2637
2638         pFcb->ObjectInformation->AllocationSize = pBuffer->AllocationSize;
2639     }
2640
2641     //
2642     // Now Tell the server if we have to
2643     //
2644     if (bTellService)
2645     {
2646         ntStatus = AFSUpdateFileInformation( &pFcb->ObjectInformation->ParentObjectInformation->FileId,
2647                                              pFcb->ObjectInformation,
2648                                              &pFcb->AuthGroup);
2649     }
2650
2651     if (NT_SUCCESS(ntStatus))
2652     {
2653         //
2654         // Trim extents if we told the service - the update has done an implicit
2655         // trim at the service.
2656         //
2657         if (bTellService)
2658         {
2659             AFSTrimExtents( pFcb,
2660                             &pFcb->Header.FileSize);
2661         }
2662
2663         KeQuerySystemTime( &pFcb->ObjectInformation->ChangeTime);
2664
2665         SetFlag( pFcb->Flags, AFS_FCB_FLAG_FILE_MODIFIED | AFS_FCB_FLAG_UPDATE_CHANGE_TIME);
2666
2667         if (bTellCc &&
2668             CcIsFileCached( pFileObject))
2669         {
2670             CcSetFileSizes( pFileObject,
2671                             (PCC_FILE_SIZES)&pFcb->Header.AllocationSize);
2672         }
2673     }
2674     else
2675     {
2676         //
2677         // Put the saved values back
2678         //
2679         pFcb->Header.ValidDataLength = liSaveVDL;
2680         pFcb->Header.FileSize = liSaveFileSize;
2681         pFcb->Header.AllocationSize = liSaveAlloc;
2682         pFcb->ObjectInformation->EndOfFile = liSaveFileSize;
2683         pFcb->ObjectInformation->AllocationSize = liSaveAlloc;
2684     }
2685
2686     if( bReleasePaging)
2687     {
2688
2689         AFSReleaseResource( &pFcb->NPFcb->PagingResource);
2690     }
2691
2692     return ntStatus;
2693 }
2694
2695 NTSTATUS
2696 AFSSetEndOfFileInfo( IN PIRP Irp,
2697                      IN AFSDirectoryCB *DirectoryCB)
2698 {
2699     NTSTATUS ntStatus = STATUS_SUCCESS;
2700     PFILE_END_OF_FILE_INFORMATION pBuffer;
2701     PIO_STACK_LOCATION pIrpSp = IoGetCurrentIrpStackLocation( Irp);
2702     PFILE_OBJECT pFileObject = pIrpSp->FileObject;
2703     LARGE_INTEGER liSaveSize;
2704     LARGE_INTEGER liSaveVDL;
2705     LARGE_INTEGER liSaveAlloc;
2706     BOOLEAN bModified = FALSE;
2707     BOOLEAN bReleasePaging = FALSE;
2708     BOOLEAN bTruncated = FALSE;
2709     AFSFcb *pFcb = NULL;
2710     AFSCcb *pCcb = NULL;
2711
2712     pFcb = (AFSFcb *)pIrpSp->FileObject->FsContext;
2713
2714     pCcb = (AFSCcb *)pIrpSp->FileObject->FsContext2;
2715
2716     pBuffer = (PFILE_END_OF_FILE_INFORMATION)Irp->AssociatedIrp.SystemBuffer;
2717
2718     liSaveSize = pFcb->Header.FileSize;
2719     liSaveAlloc = pFcb->Header.AllocationSize;
2720     liSaveVDL = pFcb->Header.ValidDataLength;
2721
2722     if( pFcb->Header.FileSize.QuadPart != pBuffer->EndOfFile.QuadPart &&
2723         !pIrpSp->Parameters.SetFile.AdvanceOnly)
2724     {
2725
2726         if( pBuffer->EndOfFile.QuadPart < pFcb->Header.FileSize.QuadPart)
2727         {
2728
2729             // Truncating the file
2730             if( !MmCanFileBeTruncated( pFileObject->SectionObjectPointer,
2731                                        &pBuffer->EndOfFile))
2732             {
2733
2734                 ntStatus = STATUS_USER_MAPPED_FILE;
2735             }
2736             else
2737             {
2738                 //
2739                 // If this is a truncation we need to grab the paging
2740                 // IO resource.
2741                 //
2742                 AFSDbgLogMsg( AFS_SUBSYSTEM_LOCK_PROCESSING,
2743                               AFS_TRACE_LEVEL_VERBOSE,
2744                               "AFSSetAllocationInfo Acquiring Fcb PagingIo lock %08lX EXCL %08lX\n",
2745                               &pFcb->NPFcb->PagingResource,
2746                               PsGetCurrentThread());
2747
2748                 AFSAcquireExcl( &pFcb->NPFcb->PagingResource,
2749                                 TRUE);
2750
2751                 bReleasePaging = TRUE;
2752
2753                 pFcb->Header.AllocationSize = pBuffer->EndOfFile;
2754
2755                 pFcb->Header.FileSize = pBuffer->EndOfFile;
2756
2757                 pFcb->ObjectInformation->EndOfFile = pBuffer->EndOfFile;
2758
2759                 pFcb->ObjectInformation->AllocationSize = pBuffer->EndOfFile;
2760
2761                 if( pFcb->Header.ValidDataLength.QuadPart > pFcb->Header.FileSize.QuadPart)
2762                 {
2763
2764                     pFcb->Header.ValidDataLength = pFcb->Header.FileSize;
2765                 }
2766
2767                 bTruncated = TRUE;
2768
2769                 bModified = TRUE;
2770             }
2771         }
2772         else
2773         {
2774             //
2775             // extending the file, move EOF
2776             //
2777
2778             pFcb->Header.FileSize = pBuffer->EndOfFile;
2779
2780             pFcb->ObjectInformation->EndOfFile = pBuffer->EndOfFile;
2781
2782             if (pFcb->Header.FileSize.QuadPart > pFcb->Header.AllocationSize.QuadPart)
2783             {
2784                 //
2785                 // And Allocation as needed.
2786                 //
2787                 pFcb->Header.AllocationSize = pBuffer->EndOfFile;
2788
2789                 pFcb->ObjectInformation->AllocationSize = pBuffer->EndOfFile;
2790             }
2791
2792             bModified = TRUE;
2793         }
2794     }
2795
2796     if (bModified)
2797     {
2798
2799         KeQuerySystemTime( &pFcb->ObjectInformation->ChangeTime);
2800
2801         SetFlag( pFcb->Flags, AFS_FCB_FLAG_FILE_MODIFIED | AFS_FCB_FLAG_UPDATE_CHANGE_TIME);
2802
2803         //
2804         // Tell the server
2805         //
2806
2807         ntStatus = AFSUpdateFileInformation( &pFcb->ObjectInformation->ParentObjectInformation->FileId,
2808                                              pFcb->ObjectInformation,
2809                                              &pFcb->AuthGroup);
2810
2811         if( NT_SUCCESS(ntStatus))
2812         {
2813             //
2814             // We are now good to go so tell CC.
2815             //
2816             CcSetFileSizes( pFileObject,
2817                             (PCC_FILE_SIZES)&pFcb->Header.AllocationSize);
2818
2819             //
2820             // And give up those extents
2821             //
2822             if( bTruncated)
2823             {
2824
2825                 AFSTrimExtents( pFcb,
2826                                 &pFcb->Header.FileSize);
2827             }
2828         }
2829         else
2830         {
2831             pFcb->Header.ValidDataLength = liSaveVDL;
2832             pFcb->Header.FileSize = liSaveSize;
2833             pFcb->Header.AllocationSize = liSaveAlloc;
2834             pFcb->ObjectInformation->EndOfFile = liSaveSize;
2835             pFcb->ObjectInformation->AllocationSize = liSaveAlloc;
2836         }
2837     }
2838
2839     if( bReleasePaging)
2840     {
2841
2842         AFSReleaseResource( &pFcb->NPFcb->PagingResource);
2843     }
2844
2845     return ntStatus;
2846 }
2847
2848 NTSTATUS
2849 AFSProcessShareSetInfo( IN IRP *Irp,
2850                         IN AFSFcb *Fcb,
2851                         IN AFSCcb *Ccb)
2852 {
2853
2854     NTSTATUS ntStatus = STATUS_SUCCESS;
2855     PIO_STACK_LOCATION pIrpSp = IoGetCurrentIrpStackLocation( Irp);
2856     ULONG ulOutputBufferLen = 0, ulInputBufferLen;
2857     FILE_INFORMATION_CLASS ulFileInformationClass;
2858     void *pPipeInfo = NULL;
2859
2860     __Enter
2861     {
2862         ulFileInformationClass = pIrpSp->Parameters.SetFile.FileInformationClass;
2863
2864         AFSDbgLogMsg( AFS_SUBSYSTEM_PIPE_PROCESSING,
2865                       AFS_TRACE_LEVEL_VERBOSE,
2866                       "AFSProcessShareSetInfo On pipe %wZ Class %08lX\n",
2867                       &Ccb->DirectoryCB->NameInformation.FileName,
2868                       ulFileInformationClass);
2869
2870         pPipeInfo = AFSLockSystemBuffer( Irp,
2871                                          pIrpSp->Parameters.SetFile.Length);
2872
2873         if( pPipeInfo == NULL)
2874         {
2875
2876             AFSDbgLogMsg( AFS_SUBSYSTEM_PIPE_PROCESSING,
2877                           AFS_TRACE_LEVEL_ERROR,
2878                           "AFSProcessShareSetInfo Failed to lock buffer on pipe %wZ\n",
2879                           &Ccb->DirectoryCB->NameInformation.FileName);
2880
2881             try_return( ntStatus = STATUS_INSUFFICIENT_RESOURCES);
2882         }
2883
2884         //
2885         // Send the request to the service
2886         //
2887
2888         ntStatus = AFSNotifySetPipeInfo( Ccb,
2889                                          (ULONG)ulFileInformationClass,
2890                                          pIrpSp->Parameters.SetFile.Length,
2891                                          pPipeInfo);
2892
2893         if( !NT_SUCCESS( ntStatus))
2894         {
2895
2896             AFSDbgLogMsg( AFS_SUBSYSTEM_PIPE_PROCESSING,
2897                           AFS_TRACE_LEVEL_ERROR,
2898                           "AFSProcessShareSetInfo Failed to send request to service on pipe %wZ Status %08lX\n",
2899                           &Ccb->DirectoryCB->NameInformation.FileName,
2900                           ntStatus);
2901
2902             try_return( ntStatus);
2903         }
2904
2905         AFSDbgLogMsg( AFS_SUBSYSTEM_PIPE_PROCESSING,
2906                       AFS_TRACE_LEVEL_VERBOSE,
2907                       "AFSProcessShareSetInfo Completed request on pipe %wZ Class %08lX\n",
2908                       &Ccb->DirectoryCB->NameInformation.FileName,
2909                       ulFileInformationClass);
2910
2911 try_exit:
2912
2913         NOTHING;
2914     }
2915
2916     return ntStatus;
2917 }
2918
2919 NTSTATUS
2920 AFSProcessShareQueryInfo( IN IRP *Irp,
2921                           IN AFSFcb *Fcb,
2922                           IN AFSCcb *Ccb)
2923 {
2924
2925     NTSTATUS ntStatus = STATUS_SUCCESS;
2926     PIO_STACK_LOCATION pIrpSp = IoGetCurrentIrpStackLocation( Irp);
2927     ULONG ulOutputBufferLen = 0, ulInputBufferLen;
2928     FILE_INFORMATION_CLASS ulFileInformationClass;
2929     void *pPipeInfo = NULL;
2930
2931     __Enter
2932     {
2933
2934         ulFileInformationClass = pIrpSp->Parameters.QueryFile.FileInformationClass;
2935
2936         AFSDbgLogMsg( AFS_SUBSYSTEM_PIPE_PROCESSING,
2937                       AFS_TRACE_LEVEL_VERBOSE,
2938                       "AFSProcessShareQueryInfo On pipe %wZ Class %08lX\n",
2939                       &Ccb->DirectoryCB->NameInformation.FileName,
2940                       ulFileInformationClass);
2941
2942         pPipeInfo = AFSLockSystemBuffer( Irp,
2943                                          pIrpSp->Parameters.QueryFile.Length);
2944
2945         if( pPipeInfo == NULL)
2946         {
2947
2948             AFSDbgLogMsg( AFS_SUBSYSTEM_PIPE_PROCESSING,
2949                           AFS_TRACE_LEVEL_ERROR,
2950                           "AFSProcessShareQueryInfo Failed to lock buffer on pipe %wZ\n",
2951                           &Ccb->DirectoryCB->NameInformation.FileName);
2952
2953             try_return( ntStatus = STATUS_INSUFFICIENT_RESOURCES);
2954         }
2955
2956         //
2957         // Send the request to the service
2958         //
2959
2960         ntStatus = AFSNotifyQueryPipeInfo( Ccb,
2961                                            (ULONG)ulFileInformationClass,
2962                                            pIrpSp->Parameters.QueryFile.Length,
2963                                            pPipeInfo,
2964                                            (ULONG *)&Irp->IoStatus.Information);
2965
2966         if( !NT_SUCCESS( ntStatus))
2967         {
2968
2969             AFSDbgLogMsg( AFS_SUBSYSTEM_PIPE_PROCESSING,
2970                           AFS_TRACE_LEVEL_ERROR,
2971                           "AFSProcessShareQueryInfo Failed to send request to service on pipe %wZ Status %08lX\n",
2972                           &Ccb->DirectoryCB->NameInformation.FileName,
2973                           ntStatus);
2974
2975             try_return( ntStatus);
2976         }
2977
2978         AFSDbgLogMsg( AFS_SUBSYSTEM_PIPE_PROCESSING,
2979                       AFS_TRACE_LEVEL_VERBOSE,
2980                       "AFSProcessShareQueryInfo Completed request on pipe %wZ Class %08lX\n",
2981                       &Ccb->DirectoryCB->NameInformation.FileName,
2982                       ulFileInformationClass);
2983
2984 try_exit:
2985
2986         NOTHING;
2987     }
2988
2989     return ntStatus;
2990 }
2991
2992 NTSTATUS
2993 AFSProcessPIOCtlQueryInfo( IN IRP *Irp,
2994                            IN AFSFcb *Fcb,
2995                            IN AFSCcb *Ccb,
2996                            IN OUT LONG *Length)
2997 {
2998
2999     NTSTATUS ntStatus = STATUS_SUCCESS;
3000     PIO_STACK_LOCATION pIrpSp = IoGetCurrentIrpStackLocation( Irp);
3001     FILE_INFORMATION_CLASS ulFileInformationClass;
3002
3003     __Enter
3004     {
3005
3006         ulFileInformationClass = pIrpSp->Parameters.QueryFile.FileInformationClass;
3007
3008         switch( ulFileInformationClass)
3009         {
3010
3011             case FileBasicInformation:
3012             {
3013
3014                 if ( *Length >= sizeof( FILE_BASIC_INFORMATION))
3015                 {
3016                     PFILE_BASIC_INFORMATION pBasic = (PFILE_BASIC_INFORMATION)Irp->AssociatedIrp.SystemBuffer;
3017
3018                     pBasic->CreationTime.QuadPart = 0;
3019                     pBasic->LastAccessTime.QuadPart = 0;
3020                     pBasic->ChangeTime.QuadPart = 0;
3021                     pBasic->LastWriteTime.QuadPart = 0;
3022                     pBasic->FileAttributes = FILE_ATTRIBUTE_SYSTEM;
3023
3024                     *Length -= sizeof( FILE_BASIC_INFORMATION);
3025                 }
3026                 else
3027                 {
3028                     ntStatus = STATUS_BUFFER_OVERFLOW;
3029                 }
3030
3031                 break;
3032             }
3033
3034             case FileStandardInformation:
3035             {
3036
3037                 if ( *Length >= sizeof( FILE_STANDARD_INFORMATION))
3038                 {
3039                     PFILE_STANDARD_INFORMATION pStandard = (PFILE_STANDARD_INFORMATION)Irp->AssociatedIrp.SystemBuffer;
3040
3041                     pStandard->NumberOfLinks = 1;
3042                     pStandard->DeletePending = 0;
3043                     pStandard->AllocationSize.QuadPart = 4096;
3044                     pStandard->EndOfFile.QuadPart = 4096;
3045                     pStandard->Directory = 0;
3046
3047                     *Length -= sizeof( FILE_STANDARD_INFORMATION);
3048                 }
3049                 else
3050                 {
3051                     ntStatus = STATUS_BUFFER_OVERFLOW;
3052                 }
3053
3054                 break;
3055             }
3056
3057             case FileNameInformation:
3058             {
3059
3060                 ULONG ulCopyLength = 0;
3061                 AFSFcb *pFcb = NULL;
3062                 AFSCcb *pCcb = NULL;
3063                 USHORT usFullNameLength = 0;
3064                 PFILE_NAME_INFORMATION pNameInfo = (PFILE_NAME_INFORMATION)Irp->AssociatedIrp.SystemBuffer;
3065                 UNICODE_STRING uniName;
3066
3067                 pFcb = (AFSFcb *)pIrpSp->FileObject->FsContext;
3068                 pCcb = (AFSCcb *)pIrpSp->FileObject->FsContext2;
3069
3070                 if( *Length < FIELD_OFFSET( FILE_NAME_INFORMATION, FileName))
3071                 {
3072                     ntStatus = STATUS_BUFFER_TOO_SMALL;
3073                     break;
3074                 }
3075
3076                 RtlZeroMemory( pNameInfo,
3077                                *Length);
3078
3079                 usFullNameLength = sizeof( WCHAR) +
3080                                             AFSServerName.Length +
3081                                             pCcb->FullFileName.Length;
3082
3083                 if( *Length >= (LONG)(FIELD_OFFSET( FILE_NAME_INFORMATION, FileName) + (LONG)usFullNameLength))
3084                 {
3085                     ulCopyLength = (LONG)usFullNameLength;
3086                 }
3087                 else
3088                 {
3089                     ulCopyLength = *Length - FIELD_OFFSET( FILE_NAME_INFORMATION, FileName);
3090                     ntStatus = STATUS_BUFFER_OVERFLOW;
3091                 }
3092
3093                 pNameInfo->FileNameLength = (ULONG)usFullNameLength;
3094
3095                 *Length -= FIELD_OFFSET( FILE_NAME_INFORMATION, FileName);
3096
3097                 if( ulCopyLength > 0)
3098                 {
3099
3100                     pNameInfo->FileName[ 0] = L'\\';
3101                     ulCopyLength -= sizeof( WCHAR);
3102
3103                     *Length -= sizeof( WCHAR);
3104
3105                     if( ulCopyLength >= AFSServerName.Length)
3106                     {
3107
3108                         RtlCopyMemory( &pNameInfo->FileName[ 1],
3109                                        AFSServerName.Buffer,
3110                                        AFSServerName.Length);
3111
3112                         ulCopyLength -= AFSServerName.Length;
3113                         *Length -= AFSServerName.Length;
3114
3115                         if( ulCopyLength >= pCcb->FullFileName.Length)
3116                         {
3117
3118                             RtlCopyMemory( &pNameInfo->FileName[ 1 + (AFSServerName.Length/sizeof( WCHAR))],
3119                                            pCcb->FullFileName.Buffer,
3120                                            pCcb->FullFileName.Length);
3121
3122                             ulCopyLength -= pCcb->FullFileName.Length;
3123                             *Length -= pCcb->FullFileName.Length;
3124
3125                             uniName.Length = (USHORT)pNameInfo->FileNameLength;
3126                             uniName.MaximumLength = uniName.Length;
3127                             uniName.Buffer = pNameInfo->FileName;
3128                         }
3129                         else
3130                         {
3131
3132                             RtlCopyMemory( &pNameInfo->FileName[ 1 + (AFSServerName.Length/sizeof( WCHAR))],
3133                                            pCcb->FullFileName.Buffer,
3134                                            ulCopyLength);
3135
3136                             *Length -= ulCopyLength;
3137
3138                             uniName.Length = (USHORT)(sizeof( WCHAR) + AFSServerName.Length + ulCopyLength);
3139                             uniName.MaximumLength = uniName.Length;
3140                             uniName.Buffer = pNameInfo->FileName;
3141                         }
3142
3143                         AFSDbgLogMsg( AFS_SUBSYSTEM_PIOCTL_PROCESSING,
3144                                       AFS_TRACE_LEVEL_VERBOSE,
3145                                       "AFSProcessPIOCtlQueryInfo (FileNameInformation) Returning %wZ\n",
3146                                       &uniName);
3147                     }
3148                 }
3149
3150                 break;
3151             }
3152
3153             case FileInternalInformation:
3154             {
3155
3156                 PFILE_INTERNAL_INFORMATION pInternalInfo = (PFILE_INTERNAL_INFORMATION)Irp->AssociatedIrp.SystemBuffer;
3157
3158                 if( *Length >= sizeof( FILE_INTERNAL_INFORMATION))
3159                 {
3160
3161                     pInternalInfo->IndexNumber.HighPart = 0;
3162
3163                     pInternalInfo->IndexNumber.LowPart = 0;
3164
3165                     *Length -= sizeof( FILE_INTERNAL_INFORMATION);
3166                 }
3167                 else
3168                 {
3169
3170                     ntStatus = STATUS_BUFFER_TOO_SMALL;
3171                 }
3172
3173                 break;
3174             }
3175
3176             default:
3177             {
3178                 ntStatus = STATUS_INVALID_PARAMETER;
3179
3180                 AFSDbgLogMsg( AFS_SUBSYSTEM_PIOCTL_PROCESSING,
3181                               AFS_TRACE_LEVEL_WARNING,
3182                               "AFSProcessPIOCtlQueryInfo Not handling request %08lX\n",
3183                               ulFileInformationClass);
3184
3185                 break;
3186             }
3187         }
3188     }
3189
3190     return ntStatus;
3191 }
3192