Windows: Adjust Last Write time handling for -1
[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, 2014 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     UNREFERENCED_PARAMETER(LibDeviceObject);
59     NTSTATUS ntStatus = STATUS_SUCCESS;
60     IO_STACK_LOCATION *pIrpSp = IoGetCurrentIrpStackLocation( Irp);
61     AFSFcb *pFcb = NULL;
62     AFSCcb *pCcb = NULL;
63     BOOLEAN bReleaseMain = FALSE;
64     LONG lLength = 0;
65     FILE_INFORMATION_CLASS stFileInformationClass;
66     GUID stAuthGroup;
67     PVOID pBuffer;
68
69     __try
70     {
71
72         //
73         // Determine the type of request this request is
74         //
75
76         pFcb = (AFSFcb *)pIrpSp->FileObject->FsContext;
77
78         pCcb = (AFSCcb *)pIrpSp->FileObject->FsContext2;
79
80         if( pFcb == NULL)
81         {
82
83             AFSDbgTrace(( AFS_SUBSYSTEM_FILE_PROCESSING,
84                           AFS_TRACE_LEVEL_ERROR,
85                           "AFSQueryFileInfo Attempted access (%p) when pFcb == NULL\n",
86                           Irp));
87
88             try_return( ntStatus = STATUS_INVALID_DEVICE_REQUEST);
89         }
90
91         lLength = (LONG)pIrpSp->Parameters.QueryFile.Length;
92         stFileInformationClass = pIrpSp->Parameters.QueryFile.FileInformationClass;
93         pBuffer = Irp->AssociatedIrp.SystemBuffer;
94
95         if ( BooleanFlagOn( pFcb->ObjectInformation->Flags, AFS_OBJECT_FLAGS_VERIFY))
96         {
97
98             RtlZeroMemory( &stAuthGroup,
99                            sizeof( GUID));
100
101             AFSRetrieveAuthGroupFnc( (ULONGLONG)PsGetCurrentProcessId(),
102                                      (ULONGLONG)PsGetCurrentThreadId(),
103                                      &stAuthGroup);
104
105             ntStatus = AFSVerifyEntry( &stAuthGroup,
106                                        pCcb->DirectoryCB,
107                                        FALSE);
108
109             if ( NT_SUCCESS( ntStatus))
110             {
111
112                 AFSDbgTrace(( AFS_SUBSYSTEM_FILE_PROCESSING,
113                               AFS_TRACE_LEVEL_VERBOSE,
114                               "AFSQueryFileInfo FID %08lX-%08lX-%08lX-%08lX Clearing Verify Flag\n",
115                               pFcb->ObjectInformation->FileId.Cell,
116                               pFcb->ObjectInformation->FileId.Volume,
117                               pFcb->ObjectInformation->FileId.Vnode,
118                               pFcb->ObjectInformation->FileId.Unique));
119
120                 ClearFlag( pFcb->ObjectInformation->Flags, AFS_OBJECT_FLAGS_VERIFY);
121             }
122             else
123             {
124
125                 ntStatus = STATUS_SUCCESS;
126             }
127         }
128
129         //
130         // Grab the main shared right off the bat
131         //
132
133         AFSDbgTrace(( AFS_SUBSYSTEM_LOCK_PROCESSING,
134                       AFS_TRACE_LEVEL_VERBOSE,
135                       "AFSQueryFileInfo Acquiring Fcb lock %p SHARED %08lX\n",
136                       &pFcb->NPFcb->Resource,
137                       PsGetCurrentThread()));
138
139         AFSAcquireShared( &pFcb->NPFcb->Resource,
140                           TRUE);
141
142         bReleaseMain = TRUE;
143
144         //
145         // Don't allow requests against IOCtl nodes
146         //
147
148         if( pFcb->Header.NodeTypeCode == AFS_SPECIAL_SHARE_FCB)
149         {
150
151             AFSDbgTrace(( AFS_SUBSYSTEM_FILE_PROCESSING,
152                           AFS_TRACE_LEVEL_VERBOSE,
153                           "AFSQueryFileInfo Processing request against SpecialShare Fcb\n"));
154
155             ntStatus = AFSProcessShareQueryInfo( Irp,
156                                                  pFcb,
157                                                  pCcb);
158
159             try_return( ntStatus);
160         }
161         else if( pFcb->Header.NodeTypeCode == AFS_IOCTL_FCB)
162         {
163             AFSDbgTrace(( AFS_SUBSYSTEM_FILE_PROCESSING,
164                           AFS_TRACE_LEVEL_VERBOSE,
165                           "AFSQueryFileInfo request against PIOCtl Fcb\n"));
166
167             ntStatus = AFSProcessPIOCtlQueryInfo( Irp,
168                                                   pFcb,
169                                                   pCcb,
170                                                   &lLength);
171
172             try_return( ntStatus);
173         }
174
175         else if( pFcb->Header.NodeTypeCode == AFS_INVALID_FCB)
176         {
177             AFSDbgTrace(( AFS_SUBSYSTEM_FILE_PROCESSING,
178                           AFS_TRACE_LEVEL_VERBOSE,
179                           "AFSQueryFileInfo request against Invalid Fcb\n"));
180
181             try_return( ntStatus = STATUS_ACCESS_DENIED);
182         }
183
184         //
185         // Process the request
186         //
187
188         switch( stFileInformationClass)
189         {
190
191             case FileAllInformation:
192             {
193
194                 PFILE_ALL_INFORMATION pAllInfo;
195
196                 //
197                 //  For the all information class we'll typecast a local
198                 //  pointer to the output buffer and then call the
199                 //  individual routines to fill in the buffer.
200                 //
201
202                 pAllInfo = (PFILE_ALL_INFORMATION)pBuffer;
203
204                 ntStatus = AFSQueryBasicInfo( Irp,
205                                               pCcb->DirectoryCB,
206                                               &pAllInfo->BasicInformation,
207                                               &lLength);
208
209                 if( !NT_SUCCESS( ntStatus))
210                 {
211
212                     try_return( ntStatus);
213                 }
214
215                 ntStatus = AFSQueryStandardInfo( Irp,
216                                                  pCcb->DirectoryCB,
217                                                  &pAllInfo->StandardInformation,
218                                                  &lLength);
219
220                 if( !NT_SUCCESS( ntStatus))
221                 {
222
223                     try_return( ntStatus);
224                 }
225
226                 ntStatus = AFSQueryInternalInfo( Irp,
227                                                  pFcb,
228                                                  &pAllInfo->InternalInformation,
229                                                  &lLength);
230
231                 if( !NT_SUCCESS( ntStatus))
232                 {
233
234                     try_return( ntStatus);
235                 }
236
237                 ntStatus = AFSQueryEaInfo( Irp,
238                                            pCcb->DirectoryCB,
239                                            &pAllInfo->EaInformation,
240                                            &lLength);
241
242                 if( !NT_SUCCESS( ntStatus))
243                 {
244
245                     try_return( ntStatus);
246                 }
247
248                 ntStatus = AFSQueryAccess( Irp,
249                                            pFcb,
250                                            &pAllInfo->AccessInformation,
251                                            &lLength);
252
253                 if( !NT_SUCCESS( ntStatus))
254                 {
255
256                     try_return( ntStatus);
257                 }
258
259                 ntStatus = AFSQueryPositionInfo( Irp,
260                                                  pFcb,
261                                                  &pAllInfo->PositionInformation,
262                                                  &lLength);
263
264                 if( !NT_SUCCESS( ntStatus))
265                 {
266
267                     try_return( ntStatus);
268                 }
269
270                 ntStatus = AFSQueryMode( Irp,
271                                          pFcb,
272                                          &pAllInfo->ModeInformation,
273                                          &lLength);
274
275                 if( !NT_SUCCESS( ntStatus))
276                 {
277
278                     try_return( ntStatus);
279                 }
280
281                 ntStatus = AFSQueryAlignment( Irp,
282                                               pFcb,
283                                               &pAllInfo->AlignmentInformation,
284                                               &lLength);
285
286                 if( !NT_SUCCESS( ntStatus))
287                 {
288
289                     try_return( ntStatus);
290                 }
291
292                 ntStatus = AFSQueryNameInfo( Irp,
293                                              pCcb->DirectoryCB,
294                                              &pAllInfo->NameInformation,
295                                              &lLength);
296
297                 if( !NT_SUCCESS( ntStatus))
298                 {
299
300                     try_return( ntStatus);
301                 }
302
303                 break;
304             }
305
306             case FileBasicInformation:
307             {
308
309                 ntStatus = AFSQueryBasicInfo( Irp,
310                                               pCcb->DirectoryCB,
311                                               (PFILE_BASIC_INFORMATION)pBuffer,
312                                               &lLength);
313
314                 break;
315             }
316
317             case FileStandardInformation:
318             {
319
320                 ntStatus = AFSQueryStandardInfo( Irp,
321                                                  pCcb->DirectoryCB,
322                                                  (PFILE_STANDARD_INFORMATION)pBuffer,
323                                                  &lLength);
324
325                 break;
326             }
327
328             case FileInternalInformation:
329             {
330
331                 ntStatus = AFSQueryInternalInfo( Irp,
332                                                  pFcb,
333                                                  (PFILE_INTERNAL_INFORMATION)pBuffer,
334                                                  &lLength);
335
336                 break;
337             }
338
339             case FileEaInformation:
340             {
341
342                 ntStatus = AFSQueryEaInfo( Irp,
343                                            pCcb->DirectoryCB,
344                                            (PFILE_EA_INFORMATION)pBuffer,
345                                            &lLength);
346
347                 break;
348             }
349
350             case FilePositionInformation:
351             {
352
353                 ntStatus = AFSQueryPositionInfo( Irp,
354                                       pFcb,
355                                       (PFILE_POSITION_INFORMATION)pBuffer,
356                                       &lLength);
357
358                 break;
359             }
360
361             case FileNormalizedNameInformation:
362             case FileNameInformation:
363             {
364
365                 ntStatus = AFSQueryNameInfo( Irp,
366                                   pCcb->DirectoryCB,
367                                   (PFILE_NAME_INFORMATION)pBuffer,
368                                   &lLength);
369
370                 break;
371             }
372
373             case FileAlternateNameInformation:
374             {
375
376                 ntStatus = AFSQueryShortNameInfo( Irp,
377                                        pCcb->DirectoryCB,
378                                        (PFILE_NAME_INFORMATION)pBuffer,
379                                        &lLength);
380
381                 break;
382             }
383
384             case FileNetworkOpenInformation:
385             {
386
387                 ntStatus = AFSQueryNetworkInfo( Irp,
388                                      pCcb->DirectoryCB,
389                                      (PFILE_NETWORK_OPEN_INFORMATION)pBuffer,
390                                      &lLength);
391
392                 break;
393             }
394
395             case FileStreamInformation:
396             {
397
398                 ntStatus = AFSQueryStreamInfo( Irp,
399                                                pCcb->DirectoryCB,
400                                                (FILE_STREAM_INFORMATION *)pBuffer,
401                                                &lLength);
402
403                 break;
404             }
405
406
407             case FileAttributeTagInformation:
408             {
409
410                 ntStatus = AFSQueryAttribTagInfo( Irp,
411                                                   pCcb->DirectoryCB,
412                                                   (FILE_ATTRIBUTE_TAG_INFORMATION *)pBuffer,
413                                                   &lLength);
414
415                 break;
416             }
417
418             case FileRemoteProtocolInformation:
419             {
420
421                     ntStatus = AFSQueryRemoteProtocolInfo( Irp,
422                                                            pCcb->DirectoryCB,
423                                                            (FILE_REMOTE_PROTOCOL_INFORMATION *)pBuffer,
424                                                            &lLength);
425
426                 break;
427             }
428
429             case FileNetworkPhysicalNameInformation:
430             {
431
432                 ntStatus = AFSQueryPhysicalNameInfo( Irp,
433                                                      pCcb->DirectoryCB,
434                                                      (FILE_NETWORK_PHYSICAL_NAME_INFORMATION *)pBuffer,
435                                                      &lLength);
436
437                 break;
438             }
439
440             default:
441             {
442                 ntStatus = STATUS_INVALID_PARAMETER;
443                 break;
444             }
445         }
446
447 try_exit:
448
449         Irp->IoStatus.Information = pIrpSp->Parameters.QueryFile.Length - lLength;
450
451         if( bReleaseMain)
452         {
453
454             AFSReleaseResource( &pFcb->NPFcb->Resource);
455         }
456
457         if( !NT_SUCCESS( ntStatus) &&
458             ntStatus != STATUS_INVALID_PARAMETER &&
459             ntStatus != STATUS_BUFFER_OVERFLOW)
460         {
461
462             if( pCcb != NULL &&
463                 pCcb->DirectoryCB != NULL)
464             {
465
466                 AFSDbgTrace(( AFS_SUBSYSTEM_FILE_PROCESSING,
467                               AFS_TRACE_LEVEL_ERROR,
468                               "AFSQueryFileInfo Failed to process request for %wZ FID %08lX-%08lX-%08lX-%08lX Status %08lX\n",
469                               &pCcb->DirectoryCB->NameInformation.FileName,
470                               pFcb->ObjectInformation->FileId.Cell,
471                               pFcb->ObjectInformation->FileId.Volume,
472                               pFcb->ObjectInformation->FileId.Vnode,
473                               pFcb->ObjectInformation->FileId.Unique,
474                               ntStatus));
475             }
476         }
477     }
478     __except( AFSExceptionFilter( __FUNCTION__, GetExceptionCode(), GetExceptionInformation()) )
479     {
480
481         AFSDbgTrace(( 0,
482                       0,
483                       "EXCEPTION - AFSQueryFileInfo\n"));
484
485         AFSDumpTraceFilesFnc();
486
487         ntStatus = STATUS_UNSUCCESSFUL;
488
489         if( bReleaseMain)
490         {
491
492             AFSReleaseResource( &pFcb->NPFcb->Resource);
493         }
494     }
495
496     AFSCompleteRequest( Irp,
497                         ntStatus);
498
499     return ntStatus;
500 }
501
502 //
503 // Function: AFSSetFileInfo
504 //
505 // Description:
506 //
507 //      This function is the dispatch handler for the IRP_MJ_SET_FILE_INFORMATION request
508 //
509 // Return:
510 //
511 //      A status is returned for the function
512 //
513
514 NTSTATUS
515 AFSSetFileInfo( IN PDEVICE_OBJECT LibDeviceObject,
516                 IN PIRP Irp)
517 {
518
519     UNREFERENCED_PARAMETER(LibDeviceObject);
520     NTSTATUS ntStatus = STATUS_SUCCESS;
521     IO_STACK_LOCATION *pIrpSp = IoGetCurrentIrpStackLocation( Irp);
522     AFSFcb *pFcb = NULL;
523     AFSCcb *pCcb = NULL;
524     FILE_INFORMATION_CLASS FileInformationClass;
525     BOOLEAN bCanQueueRequest = FALSE;
526     PFILE_OBJECT pFileObject = NULL;
527     BOOLEAN bReleaseMain = FALSE;
528     BOOLEAN bUpdateFileInfo = FALSE;
529     AFSFileID stParentFileId;
530
531     __try
532     {
533
534         pFileObject = pIrpSp->FileObject;
535
536         pFcb = (AFSFcb *)pFileObject->FsContext;
537         pCcb = (AFSCcb *)pFileObject->FsContext2;
538
539         if( pFcb == NULL)
540         {
541
542             AFSDbgTrace(( AFS_SUBSYSTEM_FILE_PROCESSING,
543                           AFS_TRACE_LEVEL_ERROR,
544                           "AFSSetFileInfo Attempted access (%p) when pFcb == NULL\n",
545                           Irp));
546
547             try_return( ntStatus = STATUS_INVALID_DEVICE_REQUEST);
548         }
549
550         bCanQueueRequest = !(IoIsOperationSynchronous( Irp) | (KeGetCurrentIrql() != PASSIVE_LEVEL));
551         FileInformationClass = pIrpSp->Parameters.SetFile.FileInformationClass;
552
553         //
554         // Grab the Fcb EXCL
555         //
556
557         AFSDbgTrace(( AFS_SUBSYSTEM_LOCK_PROCESSING,
558                       AFS_TRACE_LEVEL_VERBOSE,
559                       "AFSSetFileInfo Acquiring Fcb lock %p EXCL %08lX\n",
560                       &pFcb->NPFcb->Resource,
561                       PsGetCurrentThread()));
562
563         AFSAcquireExcl( &pFcb->NPFcb->Resource,
564                         TRUE);
565
566         bReleaseMain = TRUE;
567
568         //
569         // Don't allow requests against IOCtl nodes
570         //
571
572         if( pFcb->Header.NodeTypeCode == AFS_IOCTL_FCB)
573         {
574
575             AFSDbgTrace(( AFS_SUBSYSTEM_FILE_PROCESSING,
576                           AFS_TRACE_LEVEL_ERROR,
577                           "AFSSetFileInfo Failing request against PIOCtl Fcb\n"));
578
579             try_return( ntStatus = STATUS_INVALID_DEVICE_REQUEST);
580         }
581         else if( pFcb->Header.NodeTypeCode == AFS_SPECIAL_SHARE_FCB)
582         {
583
584             AFSDbgTrace(( AFS_SUBSYSTEM_FILE_PROCESSING,
585                           AFS_TRACE_LEVEL_VERBOSE,
586                           "AFSSetFileInfo Processing request against SpecialShare Fcb\n"));
587
588             ntStatus = AFSProcessShareSetInfo( Irp,
589                                                pFcb,
590                                                pCcb);
591
592             try_return( ntStatus);
593         }
594
595         if( FileInformationClass != FilePositionInformation &&
596             BooleanFlagOn( pFcb->ObjectInformation->VolumeCB->VolumeInformation.FileSystemAttributes, FILE_READ_ONLY_VOLUME))
597         {
598
599             AFSDbgTrace(( AFS_SUBSYSTEM_FILE_PROCESSING,
600                           AFS_TRACE_LEVEL_ERROR,
601                           "AFSSetFileInfo Request failed due to read only volume\n",
602                           Irp));
603
604             try_return( ntStatus = STATUS_MEDIA_WRITE_PROTECTED);
605         }
606
607         if( pFcb->Header.NodeTypeCode == AFS_INVALID_FCB &&
608             FileInformationClass != FileDispositionInformation)
609         {
610             AFSDbgTrace(( AFS_SUBSYSTEM_FILE_PROCESSING,
611                           AFS_TRACE_LEVEL_VERBOSE,
612                           "AFSSetFileInfo request against Invalid Fcb\n"));
613
614             try_return( ntStatus = STATUS_ACCESS_DENIED);
615         }
616
617         //
618         // Ensure rename operations are synchronous
619         //
620
621         if( FileInformationClass == FileRenameInformation)
622         {
623
624             bCanQueueRequest = FALSE;
625         }
626
627         //
628         // Store away the parent fid
629         //
630
631         RtlZeroMemory( &stParentFileId,
632                        sizeof( AFSFileID));
633
634         if( BooleanFlagOn( pFcb->ObjectInformation->Flags, AFS_OBJECT_FLAGS_PARENT_FID))
635         {
636
637             stParentFileId = pFcb->ObjectInformation->ParentFileId;
638         }
639
640         //
641         // Process the request
642         //
643
644         switch( FileInformationClass)
645         {
646
647             case FileBasicInformation:
648             {
649
650                 ntStatus = AFSSetBasicInfo( Irp,
651                                             pCcb->DirectoryCB,
652                                             &bUpdateFileInfo);
653
654                 break;
655             }
656
657             case FileDispositionInformation:
658             {
659
660                 ntStatus = AFSSetDispositionInfo( Irp,
661                                                   pCcb->DirectoryCB);
662
663                 break;
664             }
665
666             case FileRenameInformation:
667             {
668
669                 ntStatus = AFSSetRenameInfo( Irp);
670
671                 break;
672             }
673
674             case FilePositionInformation:
675             {
676
677                 ntStatus = AFSSetPositionInfo( Irp,
678                                                pCcb->DirectoryCB);
679
680                 break;
681             }
682
683             case FileLinkInformation:
684             {
685
686                 ntStatus = AFSSetFileLinkInfo( Irp);
687
688                 break;
689             }
690
691             case FileAllocationInformation:
692             {
693
694                 ntStatus = AFSSetAllocationInfo( Irp,
695                                                  pCcb->DirectoryCB);
696
697                 break;
698             }
699
700             case FileEndOfFileInformation:
701             {
702
703                 ntStatus = AFSSetEndOfFileInfo( Irp,
704                                                 pCcb->DirectoryCB);
705
706                 break;
707             }
708
709             default:
710
711                 ntStatus = STATUS_INVALID_PARAMETER;
712
713                 break;
714         }
715
716 try_exit:
717
718         if( bReleaseMain)
719         {
720
721             AFSReleaseResource( &pFcb->NPFcb->Resource);
722         }
723
724         if( NT_SUCCESS( ntStatus) &&
725             bUpdateFileInfo)
726         {
727
728             ntStatus = AFSUpdateFileInformation( &stParentFileId,
729                                                  pFcb->ObjectInformation,
730                                                  &pCcb->AuthGroup);
731
732             if( !NT_SUCCESS( ntStatus))
733             {
734
735                 AFSAcquireExcl( &pFcb->NPFcb->Resource,
736                                 TRUE);
737
738                 //
739                 // Unwind the update and fail the request
740                 //
741
742                 AFSUnwindFileInfo( pFcb,
743                                    pCcb);
744
745                 AFSDbgTrace(( AFS_SUBSYSTEM_FILE_PROCESSING,
746                               AFS_TRACE_LEVEL_ERROR,
747                               "AFSSetFileInfo Failed to send file info update to service request for %wZ FID %08lX-%08lX-%08lX-%08lX Status %08lX\n",
748                               &pCcb->DirectoryCB->NameInformation.FileName,
749                               pFcb->ObjectInformation->FileId.Cell,
750                               pFcb->ObjectInformation->FileId.Volume,
751                               pFcb->ObjectInformation->FileId.Vnode,
752                               pFcb->ObjectInformation->FileId.Unique,
753                               ntStatus));
754
755                 AFSReleaseResource( &pFcb->NPFcb->Resource);
756             }
757         }
758
759         if( !NT_SUCCESS( ntStatus))
760         {
761
762             if( pCcb != NULL &&
763                 pCcb->DirectoryCB != NULL)
764             {
765
766                 AFSDbgTrace(( AFS_SUBSYSTEM_FILE_PROCESSING,
767                               AFS_TRACE_LEVEL_ERROR,
768                               "AFSSetFileInfo Failed to process request for %wZ FID %08lX-%08lX-%08lX-%08lX Status %08lX\n",
769                               &pCcb->DirectoryCB->NameInformation.FileName,
770                               pFcb->ObjectInformation->FileId.Cell,
771                               pFcb->ObjectInformation->FileId.Volume,
772                               pFcb->ObjectInformation->FileId.Vnode,
773                               pFcb->ObjectInformation->FileId.Unique,
774                               ntStatus));
775             }
776         }
777     }
778     __except( AFSExceptionFilter( __FUNCTION__, GetExceptionCode(), GetExceptionInformation()) )
779     {
780
781         AFSDbgTrace(( 0,
782                       0,
783                       "EXCEPTION - AFSSetFileInfo\n"));
784
785         AFSDumpTraceFilesFnc();
786
787         ntStatus = STATUS_UNSUCCESSFUL;
788
789         if( bReleaseMain)
790         {
791
792             AFSReleaseResource( &pFcb->NPFcb->Resource);
793         }
794     }
795
796     AFSCompleteRequest( Irp,
797                         ntStatus);
798
799     return ntStatus;
800 }
801
802 //
803 // Function: AFSQueryBasicInfo
804 //
805 // Description:
806 //
807 //      This function is the handler for the query basic information request
808 //
809 // Return:
810 //
811 //      A status is returned for the function
812 //
813
814 NTSTATUS
815 AFSQueryBasicInfo( IN PIRP Irp,
816                    IN AFSDirectoryCB *DirectoryCB,
817                    IN OUT PFILE_BASIC_INFORMATION Buffer,
818                    IN OUT PLONG Length)
819 {
820     NTSTATUS ntStatus = STATUS_SUCCESS;
821     AFSDeviceExt *pDeviceExt = (AFSDeviceExt *)AFSRDRDeviceObject->DeviceExtension;
822     ULONG ulFileAttribs = 0;
823     AFSFcb *pFcb = NULL;
824     AFSCcb *pCcb = NULL;
825     IO_STACK_LOCATION *pIrpSp = IoGetCurrentIrpStackLocation( Irp);
826     AFSFileInfoCB stFileInfo;
827     AFSDirectoryCB *pParentDirectoryCB = NULL;
828     UNICODE_STRING uniParentPath;
829
830     if( *Length >= sizeof( FILE_BASIC_INFORMATION))
831     {
832
833         RtlZeroMemory( Buffer,
834                        *Length);
835
836         ulFileAttribs = DirectoryCB->ObjectInformation->FileAttributes;
837
838         pFcb = (AFSFcb *)pIrpSp->FileObject->FsContext;
839         pCcb = (AFSCcb *)pIrpSp->FileObject->FsContext2;
840
841         if( DirectoryCB->ObjectInformation->FileType == AFS_FILE_TYPE_SYMLINK)
842         {
843
844             pParentDirectoryCB = AFSGetParentEntry( pCcb->NameArray);
845
846             AFSRetrieveParentPath( &pCcb->FullFileName,
847                                    &uniParentPath);
848
849             RtlZeroMemory( &stFileInfo,
850                            sizeof( AFSFileInfoCB));
851
852             //
853             // Can't hold the Fcb while evaluating the path, leads to lock inversion
854             //
855
856             AFSReleaseResource( &pFcb->NPFcb->Resource);
857
858             //
859             // Its a reparse point regardless of whether the file attributes
860             // can be retrieved for the target.
861             //
862
863             if ( ulFileAttribs == FILE_ATTRIBUTE_NORMAL)
864             {
865
866                 ulFileAttribs = FILE_ATTRIBUTE_REPARSE_POINT;
867             }
868             else
869             {
870
871                 ulFileAttribs |= FILE_ATTRIBUTE_REPARSE_POINT;
872             }
873
874             if( NT_SUCCESS( AFSRetrieveFileAttributes( pParentDirectoryCB,
875                                                        DirectoryCB,
876                                                        &uniParentPath,
877                                                        pCcb->NameArray,
878                                                        &pCcb->AuthGroup,
879                                                        &stFileInfo)))
880             {
881
882                 if ( stFileInfo.FileAttributes & FILE_ATTRIBUTE_DIRECTORY)
883                 {
884
885                     ulFileAttribs |= FILE_ATTRIBUTE_DIRECTORY;
886                 }
887             }
888
889             AFSAcquireShared( &pFcb->NPFcb->Resource,
890                               TRUE);
891         }
892
893
894         AFSDbgTrace(( AFS_SUBSYSTEM_FILE_PROCESSING,
895                       AFS_TRACE_LEVEL_VERBOSE_2,
896                       "AFSQueryBasicInfo %wZ Type 0x%x Attrib 0x%x -> 0x%x\n",
897                       &pCcb->DirectoryCB->NameInformation.FileName,
898                       pFcb->ObjectInformation->FileType,
899                       pFcb->ObjectInformation->FileAttributes,
900                       ulFileAttribs));
901
902         Buffer->CreationTime = DirectoryCB->ObjectInformation->CreationTime;
903         Buffer->LastAccessTime = DirectoryCB->ObjectInformation->LastAccessTime;
904         Buffer->LastWriteTime = DirectoryCB->ObjectInformation->LastWriteTime;
905         Buffer->ChangeTime = DirectoryCB->ObjectInformation->ChangeTime;
906         Buffer->FileAttributes = ulFileAttribs;
907
908         if( DirectoryCB->NameInformation.FileName.Buffer[ 0] == L'.' &&
909             BooleanFlagOn( pDeviceExt->DeviceFlags, AFS_DEVICE_FLAG_HIDE_DOT_NAMES))
910         {
911
912             if ( Buffer->FileAttributes != FILE_ATTRIBUTE_NORMAL)
913             {
914                 Buffer->FileAttributes |= FILE_ATTRIBUTE_HIDDEN;
915             }
916             else
917             {
918                 Buffer->FileAttributes = FILE_ATTRIBUTE_HIDDEN;
919             }
920         }
921
922         *Length -= sizeof( FILE_BASIC_INFORMATION);
923     }
924     else
925     {
926
927         ntStatus = STATUS_BUFFER_TOO_SMALL;
928     }
929
930     return ntStatus;
931 }
932
933 NTSTATUS
934 AFSQueryStandardInfo( IN PIRP Irp,
935                       IN AFSDirectoryCB *DirectoryCB,
936                       IN OUT PFILE_STANDARD_INFORMATION Buffer,
937                       IN OUT PLONG Length)
938 {
939
940     NTSTATUS ntStatus = STATUS_SUCCESS;
941     AFSFcb *pFcb = NULL;
942     AFSCcb *pCcb = NULL;
943     PIO_STACK_LOCATION pIrpSp = IoGetCurrentIrpStackLocation( Irp);
944     AFSFileInfoCB stFileInfo;
945     AFSDirectoryCB *pParentDirectoryCB = NULL;
946     UNICODE_STRING uniParentPath;
947     ULONG ulFileAttribs = 0;
948
949     if( *Length >= sizeof( FILE_STANDARD_INFORMATION))
950     {
951
952         pFcb = (AFSFcb *)pIrpSp->FileObject->FsContext;
953         pCcb = (AFSCcb *)pIrpSp->FileObject->FsContext2;
954
955         RtlZeroMemory( Buffer,
956                        *Length);
957
958         Buffer->NumberOfLinks = 1;
959         Buffer->DeletePending = BooleanFlagOn( pCcb->DirectoryCB->Flags, AFS_DIR_ENTRY_PENDING_DELETE);
960
961         Buffer->AllocationSize.QuadPart = (ULONGLONG)((DirectoryCB->ObjectInformation->AllocationSize.QuadPart/PAGE_SIZE) + 1) * PAGE_SIZE;
962
963         Buffer->EndOfFile = DirectoryCB->ObjectInformation->EndOfFile;
964
965         ulFileAttribs = DirectoryCB->ObjectInformation->FileAttributes;
966
967         if( DirectoryCB->ObjectInformation->FileType == AFS_FILE_TYPE_SYMLINK)
968         {
969
970             pParentDirectoryCB = AFSGetParentEntry( pCcb->NameArray);
971
972             AFSRetrieveParentPath( &pCcb->FullFileName,
973                                    &uniParentPath);
974
975             RtlZeroMemory( &stFileInfo,
976                            sizeof( AFSFileInfoCB));
977
978             //
979             // Can't hold the Fcb while evaluating the path, leads to lock inversion
980             //
981
982             AFSReleaseResource( &pFcb->NPFcb->Resource);
983
984             //
985             // Its a reparse point regardless of whether or not the
986             // file attributes can be retrieved.
987             //
988
989             if ( ulFileAttribs == FILE_ATTRIBUTE_NORMAL)
990             {
991
992                 ulFileAttribs = FILE_ATTRIBUTE_REPARSE_POINT;
993             }
994             else
995             {
996
997                 ulFileAttribs |= FILE_ATTRIBUTE_REPARSE_POINT;
998             }
999
1000             if( NT_SUCCESS( AFSRetrieveFileAttributes( pParentDirectoryCB,
1001                                                        DirectoryCB,
1002                                                        &uniParentPath,
1003                                                        pCcb->NameArray,
1004                                                        &pCcb->AuthGroup,
1005                                                        &stFileInfo)))
1006             {
1007
1008                 if ( stFileInfo.FileAttributes & FILE_ATTRIBUTE_DIRECTORY)
1009                 {
1010
1011                     ulFileAttribs |= FILE_ATTRIBUTE_DIRECTORY;
1012                 }
1013             }
1014
1015             AFSAcquireShared( &pFcb->NPFcb->Resource,
1016                               TRUE);
1017         }
1018
1019         AFSDbgTrace(( AFS_SUBSYSTEM_FILE_PROCESSING,
1020                       AFS_TRACE_LEVEL_VERBOSE_2,
1021                       "AFSQueryStandardInfo %wZ Type 0x%x Attrib 0x%x -> 0x%x\n",
1022                       &pCcb->DirectoryCB->NameInformation.FileName,
1023                       pFcb->ObjectInformation->FileType,
1024                       pFcb->ObjectInformation->FileAttributes,
1025                       ulFileAttribs));
1026
1027         Buffer->Directory = BooleanFlagOn( ulFileAttribs, FILE_ATTRIBUTE_DIRECTORY);
1028
1029         *Length -= sizeof( FILE_STANDARD_INFORMATION);
1030     }
1031     else
1032     {
1033
1034         ntStatus = STATUS_BUFFER_TOO_SMALL;
1035     }
1036
1037     return ntStatus;
1038 }
1039
1040 NTSTATUS
1041 AFSQueryInternalInfo( IN PIRP Irp,
1042                       IN AFSFcb *Fcb,
1043                       IN OUT PFILE_INTERNAL_INFORMATION Buffer,
1044                       IN OUT PLONG Length)
1045 {
1046
1047     UNREFERENCED_PARAMETER(Irp);
1048     NTSTATUS ntStatus = STATUS_SUCCESS;
1049
1050     if( *Length >= sizeof( FILE_INTERNAL_INFORMATION))
1051     {
1052
1053         Buffer->IndexNumber.HighPart = Fcb->ObjectInformation->FileId.Vnode;
1054
1055         Buffer->IndexNumber.LowPart = Fcb->ObjectInformation->FileId.Unique;
1056
1057         *Length -= sizeof( FILE_INTERNAL_INFORMATION);
1058     }
1059     else
1060     {
1061
1062         ntStatus = STATUS_BUFFER_TOO_SMALL;
1063     }
1064
1065     return ntStatus;
1066 }
1067
1068 NTSTATUS
1069 AFSQueryEaInfo( IN PIRP Irp,
1070                 IN AFSDirectoryCB *DirectoryCB,
1071                 IN OUT PFILE_EA_INFORMATION Buffer,
1072                 IN OUT PLONG Length)
1073 {
1074
1075     UNREFERENCED_PARAMETER(Irp);
1076     UNREFERENCED_PARAMETER(DirectoryCB);
1077     NTSTATUS ntStatus = STATUS_SUCCESS;
1078
1079     RtlZeroMemory( Buffer,
1080                    *Length);
1081
1082     if( *Length >= sizeof( FILE_EA_INFORMATION))
1083     {
1084
1085         Buffer->EaSize = 0;
1086
1087         *Length -= sizeof( FILE_EA_INFORMATION);
1088     }
1089     else
1090     {
1091
1092         ntStatus = STATUS_BUFFER_TOO_SMALL;
1093     }
1094
1095     return ntStatus;
1096 }
1097
1098 NTSTATUS
1099 AFSQueryPositionInfo( IN PIRP Irp,
1100                       IN AFSFcb *Fcb,
1101                       IN OUT PFILE_POSITION_INFORMATION Buffer,
1102                       IN OUT PLONG Length)
1103 {
1104
1105     UNREFERENCED_PARAMETER(Fcb);
1106     NTSTATUS ntStatus = STATUS_SUCCESS;
1107     PIO_STACK_LOCATION pIrpSp = IoGetCurrentIrpStackLocation( Irp);
1108
1109     if( *Length >= sizeof( FILE_POSITION_INFORMATION))
1110     {
1111
1112         RtlZeroMemory( Buffer,
1113                        *Length);
1114
1115         Buffer->CurrentByteOffset.QuadPart = pIrpSp->FileObject->CurrentByteOffset.QuadPart;
1116
1117         *Length -= sizeof( FILE_POSITION_INFORMATION);
1118     }
1119     else
1120     {
1121
1122         ntStatus = STATUS_BUFFER_TOO_SMALL;
1123     }
1124
1125     return ntStatus;
1126 }
1127
1128 NTSTATUS
1129 AFSQueryAccess( IN PIRP Irp,
1130                 IN AFSFcb *Fcb,
1131                 IN OUT PFILE_ACCESS_INFORMATION Buffer,
1132                 IN OUT PLONG Length)
1133 {
1134
1135     UNREFERENCED_PARAMETER(Irp);
1136     UNREFERENCED_PARAMETER(Fcb);
1137     NTSTATUS ntStatus = STATUS_SUCCESS;
1138
1139     if( *Length >= sizeof( FILE_ACCESS_INFORMATION))
1140     {
1141
1142         RtlZeroMemory( Buffer,
1143                        *Length);
1144
1145         Buffer->AccessFlags = 0;
1146
1147         *Length -= sizeof( FILE_ACCESS_INFORMATION);
1148     }
1149     else
1150     {
1151
1152         ntStatus = STATUS_BUFFER_TOO_SMALL;
1153     }
1154
1155     return ntStatus;
1156 }
1157
1158 NTSTATUS
1159 AFSQueryMode( IN PIRP Irp,
1160               IN AFSFcb *Fcb,
1161               IN OUT PFILE_MODE_INFORMATION Buffer,
1162               IN OUT PLONG Length)
1163 {
1164
1165     UNREFERENCED_PARAMETER(Irp);
1166     UNREFERENCED_PARAMETER(Fcb);
1167     NTSTATUS ntStatus = STATUS_SUCCESS;
1168
1169     if( *Length >= sizeof( FILE_MODE_INFORMATION))
1170     {
1171
1172         RtlZeroMemory( Buffer,
1173                        *Length);
1174
1175         Buffer->Mode = 0;
1176
1177         *Length -= sizeof( FILE_MODE_INFORMATION);
1178     }
1179     else
1180     {
1181
1182         ntStatus = STATUS_BUFFER_TOO_SMALL;
1183     }
1184
1185     return ntStatus;
1186 }
1187
1188 NTSTATUS
1189 AFSQueryAlignment( IN PIRP Irp,
1190                    IN AFSFcb *Fcb,
1191                    IN OUT PFILE_ALIGNMENT_INFORMATION Buffer,
1192                    IN OUT PLONG Length)
1193 {
1194
1195     UNREFERENCED_PARAMETER(Irp);
1196     UNREFERENCED_PARAMETER(Fcb);
1197     NTSTATUS ntStatus = STATUS_SUCCESS;
1198
1199     if( *Length >= sizeof( FILE_ALIGNMENT_INFORMATION))
1200     {
1201
1202         RtlZeroMemory( Buffer,
1203                        *Length);
1204
1205         Buffer->AlignmentRequirement = 1;
1206
1207         *Length -= sizeof( FILE_ALIGNMENT_INFORMATION);
1208     }
1209     else
1210     {
1211
1212         ntStatus = STATUS_BUFFER_TOO_SMALL;
1213     }
1214
1215     return ntStatus;
1216 }
1217
1218 NTSTATUS
1219 AFSQueryNameInfo( IN PIRP Irp,
1220                   IN AFSDirectoryCB *DirectoryCB,
1221                   IN OUT PFILE_NAME_INFORMATION Buffer,
1222                   IN OUT PLONG Length)
1223 {
1224
1225     UNREFERENCED_PARAMETER(DirectoryCB);
1226     NTSTATUS ntStatus = STATUS_SUCCESS;
1227     ULONG ulCopyLength = 0;
1228     ULONG cchCopied = 0;
1229     AFSFcb *pFcb = NULL;
1230     AFSCcb *pCcb = NULL;
1231     IO_STACK_LOCATION *pIrpSp = IoGetCurrentIrpStackLocation( Irp);
1232     BOOLEAN bAddLeadingSlash = FALSE;
1233     BOOLEAN bAddTrailingSlash = FALSE;
1234     USHORT usFullNameLength = 0;
1235
1236     pFcb = (AFSFcb *)pIrpSp->FileObject->FsContext;
1237
1238     pCcb = (AFSCcb *)pIrpSp->FileObject->FsContext2;
1239
1240     if( *Length >= FIELD_OFFSET( FILE_NAME_INFORMATION, FileName))
1241     {
1242
1243         RtlZeroMemory( Buffer,
1244                        *Length);
1245
1246         if( pCcb->FullFileName.Length == 0 ||
1247             pCcb->FullFileName.Buffer[ 0] != L'\\')
1248         {
1249             bAddLeadingSlash = TRUE;
1250         }
1251
1252         if( pFcb->ObjectInformation->FileType == AFS_FILE_TYPE_DIRECTORY &&
1253             pCcb->FullFileName.Length > 0 &&
1254             pCcb->FullFileName.Buffer[ (pCcb->FullFileName.Length/sizeof( WCHAR)) - 1] != L'\\')
1255         {
1256             bAddTrailingSlash = TRUE;
1257         }
1258
1259         usFullNameLength = sizeof( WCHAR) +
1260                                     AFSServerName.Length +
1261                                     pCcb->FullFileName.Length;
1262
1263         if( bAddLeadingSlash)
1264         {
1265             usFullNameLength += sizeof( WCHAR);
1266         }
1267
1268         if( bAddTrailingSlash)
1269         {
1270             usFullNameLength += sizeof( WCHAR);
1271         }
1272
1273         if( *Length >= (LONG)(FIELD_OFFSET( FILE_NAME_INFORMATION, FileName) + (LONG)usFullNameLength))
1274         {
1275
1276             ulCopyLength = (LONG)usFullNameLength;
1277         }
1278         else
1279         {
1280
1281             ulCopyLength = *Length - FIELD_OFFSET( FILE_NAME_INFORMATION, FileName);
1282
1283             ntStatus = STATUS_BUFFER_OVERFLOW;
1284         }
1285
1286         Buffer->FileNameLength = (ULONG)usFullNameLength;
1287
1288         *Length -= FIELD_OFFSET( FILE_NAME_INFORMATION, FileName);
1289
1290         if( ulCopyLength > 0)
1291         {
1292
1293             Buffer->FileName[ 0] = L'\\';
1294             ulCopyLength -= sizeof( WCHAR);
1295
1296             *Length -= sizeof( WCHAR);
1297             cchCopied += 1;
1298
1299             if( ulCopyLength >= AFSServerName.Length)
1300             {
1301
1302                 RtlCopyMemory( &Buffer->FileName[ 1],
1303                                AFSServerName.Buffer,
1304                                AFSServerName.Length);
1305
1306                 ulCopyLength -= AFSServerName.Length;
1307                 *Length -= AFSServerName.Length;
1308                 cchCopied += AFSServerName.Length/sizeof( WCHAR);
1309
1310                 if ( ulCopyLength > 0 &&
1311                      bAddLeadingSlash)
1312                 {
1313
1314                     Buffer->FileName[ cchCopied] = L'\\';
1315
1316                     ulCopyLength -= sizeof( WCHAR);
1317                     *Length -= sizeof( WCHAR);
1318                     cchCopied++;
1319                 }
1320
1321                 if( ulCopyLength >= pCcb->FullFileName.Length)
1322                 {
1323
1324                     RtlCopyMemory( &Buffer->FileName[ cchCopied],
1325                                    pCcb->FullFileName.Buffer,
1326                                    pCcb->FullFileName.Length);
1327
1328                     ulCopyLength -= pCcb->FullFileName.Length;
1329                     *Length -= pCcb->FullFileName.Length;
1330                     cchCopied += pCcb->FullFileName.Length/sizeof( WCHAR);
1331
1332                     if( ulCopyLength > 0 &&
1333                         bAddTrailingSlash)
1334                     {
1335                         Buffer->FileName[ cchCopied] = L'\\';
1336
1337                         *Length -= sizeof( WCHAR);
1338                     }
1339                 }
1340                 else
1341                 {
1342
1343                     RtlCopyMemory( &Buffer->FileName[ cchCopied],
1344                                    pCcb->FullFileName.Buffer,
1345                                    ulCopyLength);
1346
1347                     *Length -= ulCopyLength;
1348                 }
1349             }
1350         }
1351     }
1352     else
1353     {
1354
1355         ntStatus = STATUS_BUFFER_TOO_SMALL;
1356     }
1357
1358     return ntStatus;
1359 }
1360
1361 NTSTATUS
1362 AFSQueryShortNameInfo( IN PIRP Irp,
1363                        IN AFSDirectoryCB *DirectoryCB,
1364                        IN OUT PFILE_NAME_INFORMATION Buffer,
1365                        IN OUT PLONG Length)
1366 {
1367
1368     UNREFERENCED_PARAMETER(Irp);
1369     NTSTATUS ntStatus = STATUS_BUFFER_TOO_SMALL;
1370     ULONG ulCopyLength = 0;
1371
1372     RtlZeroMemory( Buffer,
1373                    *Length);
1374
1375     if( DirectoryCB->NameInformation.ShortNameLength == 0)
1376     {
1377
1378         //
1379         // The short name IS the long name
1380         //
1381
1382         if( *Length >= (LONG)FIELD_OFFSET( FILE_NAME_INFORMATION, FileName))
1383         {
1384
1385             if( *Length >= (LONG)(FIELD_OFFSET( FILE_NAME_INFORMATION, FileName) + (LONG)DirectoryCB->NameInformation.FileName.Length))
1386             {
1387
1388                 ulCopyLength = (LONG)DirectoryCB->NameInformation.FileName.Length;
1389
1390                 ntStatus = STATUS_SUCCESS;
1391             }
1392             else
1393             {
1394
1395                 ulCopyLength = *Length - FIELD_OFFSET( FILE_NAME_INFORMATION, FileName);
1396
1397                 ntStatus = STATUS_BUFFER_OVERFLOW;
1398             }
1399
1400             Buffer->FileNameLength = DirectoryCB->NameInformation.FileName.Length;
1401
1402             *Length -= FIELD_OFFSET( FILE_NAME_INFORMATION, FileName);
1403
1404             if( ulCopyLength > 0)
1405             {
1406
1407                 RtlCopyMemory( Buffer->FileName,
1408                                DirectoryCB->NameInformation.FileName.Buffer,
1409                                ulCopyLength);
1410
1411                 *Length -= ulCopyLength;
1412             }
1413         }
1414     }
1415     else
1416     {
1417
1418         if( *Length >= (LONG)FIELD_OFFSET( FILE_NAME_INFORMATION, FileName))
1419         {
1420
1421             if( *Length >= (LONG)(FIELD_OFFSET( FILE_NAME_INFORMATION, FileName) + (LONG)DirectoryCB->NameInformation.FileName.Length))
1422             {
1423
1424                 ulCopyLength = (LONG)DirectoryCB->NameInformation.ShortNameLength;
1425
1426                 ntStatus = STATUS_SUCCESS;
1427             }
1428             else
1429             {
1430
1431                 ulCopyLength = *Length - FIELD_OFFSET( FILE_NAME_INFORMATION, FileName);
1432
1433                 ntStatus = STATUS_BUFFER_OVERFLOW;
1434             }
1435
1436             Buffer->FileNameLength = DirectoryCB->NameInformation.ShortNameLength;
1437
1438             *Length -= FIELD_OFFSET( FILE_NAME_INFORMATION, FileName);
1439
1440             if( ulCopyLength > 0)
1441             {
1442
1443                 RtlCopyMemory( Buffer->FileName,
1444                                DirectoryCB->NameInformation.ShortName,
1445                                Buffer->FileNameLength);
1446
1447                 *Length -= ulCopyLength;
1448             }
1449         }
1450     }
1451
1452     return ntStatus;
1453 }
1454
1455 NTSTATUS
1456 AFSQueryNetworkInfo( IN PIRP Irp,
1457                      IN AFSDirectoryCB *DirectoryCB,
1458                      IN OUT PFILE_NETWORK_OPEN_INFORMATION Buffer,
1459                      IN OUT PLONG Length)
1460 {
1461
1462     NTSTATUS ntStatus = STATUS_SUCCESS;
1463     AFSDeviceExt *pDeviceExt = (AFSDeviceExt *)AFSRDRDeviceObject->DeviceExtension;
1464     AFSFcb *pFcb = NULL;
1465     AFSCcb *pCcb = NULL;
1466     PIO_STACK_LOCATION pIrpSp = IoGetCurrentIrpStackLocation( Irp);
1467     AFSFileInfoCB stFileInfo;
1468     AFSDirectoryCB *pParentDirectoryCB = NULL;
1469     UNICODE_STRING uniParentPath;
1470     ULONG ulFileAttribs = 0;
1471
1472     RtlZeroMemory( Buffer,
1473                    *Length);
1474
1475     if( *Length >= sizeof( FILE_NETWORK_OPEN_INFORMATION))
1476     {
1477
1478         ulFileAttribs = DirectoryCB->ObjectInformation->FileAttributes;
1479
1480         pFcb = (AFSFcb *)pIrpSp->FileObject->FsContext;
1481         pCcb = (AFSCcb *)pIrpSp->FileObject->FsContext2;
1482
1483         if( DirectoryCB->ObjectInformation->FileType == AFS_FILE_TYPE_SYMLINK)
1484         {
1485
1486             pParentDirectoryCB = AFSGetParentEntry( pCcb->NameArray);
1487
1488             AFSRetrieveParentPath( &pCcb->FullFileName,
1489                                    &uniParentPath);
1490
1491             RtlZeroMemory( &stFileInfo,
1492                            sizeof( AFSFileInfoCB));
1493
1494             //
1495             // Can't hold the Fcb while evaluating the path, leads to lock inversion
1496             //
1497
1498             AFSReleaseResource( &pFcb->NPFcb->Resource);
1499
1500             //
1501             // Its a reparse point regardless of whether the file attributes
1502             // can be retrieved for the target.
1503             //
1504
1505             if ( ulFileAttribs == FILE_ATTRIBUTE_NORMAL)
1506             {
1507
1508                 ulFileAttribs = FILE_ATTRIBUTE_REPARSE_POINT;
1509             }
1510             else
1511             {
1512
1513                 ulFileAttribs |= FILE_ATTRIBUTE_REPARSE_POINT;
1514             }
1515
1516             if( NT_SUCCESS( AFSRetrieveFileAttributes( pParentDirectoryCB,
1517                                                        DirectoryCB,
1518                                                        &uniParentPath,
1519                                                        pCcb->NameArray,
1520                                                        &pCcb->AuthGroup,
1521                                                        &stFileInfo)))
1522             {
1523
1524                 if ( stFileInfo.FileAttributes & FILE_ATTRIBUTE_DIRECTORY)
1525                 {
1526
1527                     ulFileAttribs |= FILE_ATTRIBUTE_DIRECTORY;
1528                 }
1529             }
1530
1531             AFSAcquireShared( &pFcb->NPFcb->Resource,
1532                               TRUE);
1533         }
1534
1535         AFSDbgTrace(( AFS_SUBSYSTEM_FILE_PROCESSING,
1536                       AFS_TRACE_LEVEL_VERBOSE_2,
1537                       "AFSQueryNetworkInfo %wZ Type 0x%x Attrib 0x%x -> 0x%x\n",
1538                       &pCcb->DirectoryCB->NameInformation.FileName,
1539                       pFcb->ObjectInformation->FileType,
1540                       pFcb->ObjectInformation->FileAttributes,
1541                       ulFileAttribs));
1542
1543         Buffer->CreationTime.QuadPart = DirectoryCB->ObjectInformation->CreationTime.QuadPart;
1544         Buffer->LastAccessTime.QuadPart = DirectoryCB->ObjectInformation->LastAccessTime.QuadPart;
1545         Buffer->LastWriteTime.QuadPart = DirectoryCB->ObjectInformation->LastWriteTime.QuadPart;
1546         Buffer->ChangeTime.QuadPart = DirectoryCB->ObjectInformation->ChangeTime.QuadPart;
1547
1548         Buffer->AllocationSize.QuadPart = DirectoryCB->ObjectInformation->AllocationSize.QuadPart;
1549         Buffer->EndOfFile.QuadPart = DirectoryCB->ObjectInformation->EndOfFile.QuadPart;
1550
1551         Buffer->FileAttributes = ulFileAttribs;
1552
1553         if( DirectoryCB->NameInformation.FileName.Buffer[ 0] == L'.' &&
1554             BooleanFlagOn( pDeviceExt->DeviceFlags, AFS_DEVICE_FLAG_HIDE_DOT_NAMES))
1555         {
1556
1557             if ( Buffer->FileAttributes != FILE_ATTRIBUTE_NORMAL)
1558             {
1559
1560                 Buffer->FileAttributes |= FILE_ATTRIBUTE_HIDDEN;
1561             }
1562             else
1563             {
1564
1565                 Buffer->FileAttributes = FILE_ATTRIBUTE_HIDDEN;
1566             }
1567         }
1568
1569         *Length -= sizeof( FILE_NETWORK_OPEN_INFORMATION);
1570     }
1571     else
1572     {
1573
1574         ntStatus = STATUS_BUFFER_TOO_SMALL;
1575     }
1576
1577     return ntStatus;
1578 }
1579
1580 NTSTATUS
1581 AFSQueryStreamInfo( IN PIRP Irp,
1582                     IN AFSDirectoryCB *DirectoryCB,
1583                     IN OUT FILE_STREAM_INFORMATION *Buffer,
1584                     IN OUT PLONG Length)
1585 {
1586
1587     UNREFERENCED_PARAMETER(Irp);
1588     NTSTATUS ntStatus = STATUS_BUFFER_TOO_SMALL;
1589     ULONG ulCopyLength = 0;
1590
1591     if( *Length >= FIELD_OFFSET( FILE_STREAM_INFORMATION, StreamName))
1592     {
1593
1594         RtlZeroMemory( Buffer,
1595                        *Length);
1596
1597         Buffer->NextEntryOffset = 0;
1598
1599
1600         if( !BooleanFlagOn( DirectoryCB->ObjectInformation->FileAttributes, FILE_ATTRIBUTE_DIRECTORY))
1601         {
1602
1603             if( *Length >= (LONG)(FIELD_OFFSET( FILE_STREAM_INFORMATION, StreamName) + 14))  // ::$DATA
1604             {
1605
1606                 ulCopyLength = 14;
1607
1608                 ntStatus = STATUS_SUCCESS;
1609             }
1610             else
1611             {
1612
1613                 ulCopyLength = *Length - FIELD_OFFSET( FILE_STREAM_INFORMATION, StreamName);
1614
1615                 ntStatus = STATUS_BUFFER_OVERFLOW;
1616             }
1617
1618             Buffer->StreamNameLength = 14; // ::$DATA
1619
1620             Buffer->StreamSize.QuadPart = DirectoryCB->ObjectInformation->EndOfFile.QuadPart;
1621
1622             Buffer->StreamAllocationSize.QuadPart = DirectoryCB->ObjectInformation->AllocationSize.QuadPart;
1623
1624             *Length -= FIELD_OFFSET( FILE_STREAM_INFORMATION, StreamName);
1625
1626             if( ulCopyLength > 0)
1627             {
1628
1629                 RtlCopyMemory( Buffer->StreamName,
1630                                L"::$DATA",
1631                                ulCopyLength);
1632
1633                 *Length -= ulCopyLength;
1634             }
1635         }
1636         else
1637         {
1638
1639             Buffer->StreamNameLength = 0;       // No stream for a directory
1640
1641             // The response size is zero
1642
1643             ntStatus = STATUS_SUCCESS;
1644         }
1645     }
1646
1647     return ntStatus;
1648 }
1649
1650 NTSTATUS
1651 AFSQueryAttribTagInfo( IN PIRP Irp,
1652                        IN AFSDirectoryCB *DirectoryCB,
1653                        IN OUT FILE_ATTRIBUTE_TAG_INFORMATION *Buffer,
1654                        IN OUT PLONG Length)
1655 {
1656
1657     NTSTATUS ntStatus = STATUS_BUFFER_TOO_SMALL;
1658     AFSDeviceExt *pDeviceExt = (AFSDeviceExt *)AFSRDRDeviceObject->DeviceExtension;
1659     AFSFcb *pFcb = NULL;
1660     AFSCcb *pCcb = NULL;
1661     PIO_STACK_LOCATION pIrpSp = IoGetCurrentIrpStackLocation( Irp);
1662     AFSFileInfoCB stFileInfo;
1663     AFSDirectoryCB *pParentDirectoryCB = NULL;
1664     UNICODE_STRING uniParentPath;
1665     ULONG ulFileAttribs = 0;
1666
1667     if( *Length >= sizeof( FILE_ATTRIBUTE_TAG_INFORMATION))
1668     {
1669
1670         RtlZeroMemory( Buffer,
1671                        *Length);
1672
1673         ulFileAttribs = DirectoryCB->ObjectInformation->FileAttributes;
1674
1675         pFcb = (AFSFcb *)pIrpSp->FileObject->FsContext;
1676         pCcb = (AFSCcb *)pIrpSp->FileObject->FsContext2;
1677
1678         if( DirectoryCB->ObjectInformation->FileType == AFS_FILE_TYPE_SYMLINK)
1679         {
1680
1681             pParentDirectoryCB = AFSGetParentEntry( pCcb->NameArray);
1682
1683             AFSRetrieveParentPath( &pCcb->FullFileName,
1684                                    &uniParentPath);
1685
1686             RtlZeroMemory( &stFileInfo,
1687                            sizeof( AFSFileInfoCB));
1688
1689             //
1690             // Can't hold the Fcb while evaluating the path, leads to lock inversion
1691             //
1692
1693             AFSReleaseResource( &pFcb->NPFcb->Resource);
1694
1695             //
1696             // Its a reparse point regardless of whether the file attributes
1697             // can be retrieved for the target.
1698             //
1699
1700             if ( ulFileAttribs == FILE_ATTRIBUTE_NORMAL)
1701             {
1702
1703                 ulFileAttribs = FILE_ATTRIBUTE_REPARSE_POINT;
1704             }
1705             else
1706             {
1707
1708                 ulFileAttribs |= FILE_ATTRIBUTE_REPARSE_POINT;
1709             }
1710
1711             if( NT_SUCCESS( AFSRetrieveFileAttributes( pParentDirectoryCB,
1712                                                        DirectoryCB,
1713                                                        &uniParentPath,
1714                                                        pCcb->NameArray,
1715                                                        &pCcb->AuthGroup,
1716                                                        &stFileInfo)))
1717             {
1718
1719                 if ( stFileInfo.FileAttributes & FILE_ATTRIBUTE_DIRECTORY)
1720                 {
1721
1722                     ulFileAttribs |= FILE_ATTRIBUTE_DIRECTORY;
1723                 }
1724             }
1725
1726             AFSAcquireShared( &pFcb->NPFcb->Resource,
1727                               TRUE);
1728         }
1729
1730         AFSDbgTrace(( AFS_SUBSYSTEM_FILE_PROCESSING,
1731                       AFS_TRACE_LEVEL_VERBOSE_2,
1732                       "AFSAttribTagInfo %wZ Type 0x%x Attrib 0x%x -> 0x%x\n",
1733                       &pCcb->DirectoryCB->NameInformation.FileName,
1734                       pFcb->ObjectInformation->FileType,
1735                       pFcb->ObjectInformation->FileAttributes,
1736                       ulFileAttribs));
1737
1738         Buffer->FileAttributes = ulFileAttribs;
1739
1740         if( DirectoryCB->NameInformation.FileName.Buffer[ 0] == L'.' &&
1741             BooleanFlagOn( pDeviceExt->DeviceFlags, AFS_DEVICE_FLAG_HIDE_DOT_NAMES))
1742         {
1743
1744             if ( Buffer->FileAttributes != FILE_ATTRIBUTE_NORMAL)
1745             {
1746
1747                 Buffer->FileAttributes |= FILE_ATTRIBUTE_HIDDEN;
1748             }
1749             else
1750             {
1751
1752                 Buffer->FileAttributes = FILE_ATTRIBUTE_HIDDEN;
1753             }
1754         }
1755
1756         if ( DirectoryCB->ObjectInformation->FileType == AFS_FILE_TYPE_MOUNTPOINT)
1757         {
1758
1759             Buffer->ReparseTag = IO_REPARSE_TAG_SURROGATE|IO_REPARSE_TAG_OPENAFS_DFS;
1760         }
1761         else if( BooleanFlagOn( DirectoryCB->ObjectInformation->FileAttributes, FILE_ATTRIBUTE_REPARSE_POINT))
1762         {
1763
1764             Buffer->ReparseTag = IO_REPARSE_TAG_SYMLINK;
1765         }
1766
1767         *Length -= sizeof( FILE_ATTRIBUTE_TAG_INFORMATION);
1768
1769         ntStatus = STATUS_SUCCESS;
1770     }
1771
1772     return ntStatus;
1773 }
1774
1775 NTSTATUS
1776 AFSQueryRemoteProtocolInfo( IN PIRP Irp,
1777                             IN AFSDirectoryCB *DirectoryCB,
1778                             IN OUT FILE_REMOTE_PROTOCOL_INFORMATION *Buffer,
1779                             IN OUT PLONG Length)
1780 {
1781
1782     UNREFERENCED_PARAMETER(Irp);
1783     UNREFERENCED_PARAMETER(DirectoryCB);
1784     NTSTATUS ntStatus = STATUS_BUFFER_TOO_SMALL;
1785
1786     if( *Length >= sizeof( FILE_REMOTE_PROTOCOL_INFORMATION))
1787     {
1788
1789         RtlZeroMemory( Buffer,
1790                        *Length);
1791
1792         Buffer->StructureVersion = 1;
1793
1794         Buffer->StructureSize = sizeof(FILE_REMOTE_PROTOCOL_INFORMATION);
1795
1796         Buffer->Protocol = WNNC_NET_OPENAFS;
1797
1798         Buffer->ProtocolMajorVersion = 3;
1799
1800         Buffer->ProtocolMinorVersion = 0;
1801
1802         Buffer->ProtocolRevision = 0;
1803
1804         *Length -= sizeof( FILE_REMOTE_PROTOCOL_INFORMATION);
1805
1806         ntStatus = STATUS_SUCCESS;
1807     }
1808
1809     return ntStatus;
1810 }
1811
1812 NTSTATUS
1813 AFSQueryPhysicalNameInfo( IN PIRP Irp,
1814                           IN AFSDirectoryCB *DirectoryCB,
1815                           IN OUT PFILE_NETWORK_PHYSICAL_NAME_INFORMATION Buffer,
1816                           IN OUT PLONG Length)
1817 {
1818
1819     UNREFERENCED_PARAMETER(DirectoryCB);
1820     NTSTATUS ntStatus = STATUS_SUCCESS;
1821     ULONG ulCopyLength = 0;
1822     ULONG cchCopied = 0;
1823     AFSFcb *pFcb = NULL;
1824     AFSCcb *pCcb = NULL;
1825     IO_STACK_LOCATION *pIrpSp = IoGetCurrentIrpStackLocation( Irp);
1826     BOOLEAN bAddLeadingSlash = FALSE;
1827     USHORT usFullNameLength = 0;
1828
1829     pFcb = (AFSFcb *)pIrpSp->FileObject->FsContext;
1830
1831     pCcb = (AFSCcb *)pIrpSp->FileObject->FsContext2;
1832
1833     if( *Length >= FIELD_OFFSET( FILE_NETWORK_PHYSICAL_NAME_INFORMATION, FileName))
1834     {
1835
1836         RtlZeroMemory( Buffer,
1837                        *Length);
1838
1839         if( pCcb->FullFileName.Length == 0 ||
1840             pCcb->FullFileName.Buffer[ 0] != L'\\')
1841         {
1842             bAddLeadingSlash = TRUE;
1843         }
1844
1845         usFullNameLength = pCcb->FullFileName.Length;
1846
1847         if( bAddLeadingSlash)
1848         {
1849             usFullNameLength += sizeof( WCHAR);
1850         }
1851
1852         if( *Length >= (LONG)(FIELD_OFFSET( FILE_NETWORK_PHYSICAL_NAME_INFORMATION, FileName) + (LONG)usFullNameLength))
1853         {
1854             ulCopyLength = (LONG)usFullNameLength;
1855         }
1856         else
1857         {
1858
1859             ulCopyLength = *Length - FIELD_OFFSET( FILE_NETWORK_PHYSICAL_NAME_INFORMATION, FileName);
1860
1861             ntStatus = STATUS_BUFFER_OVERFLOW;
1862         }
1863
1864         Buffer->FileNameLength = (ULONG)usFullNameLength;
1865
1866         *Length -= FIELD_OFFSET( FILE_NETWORK_PHYSICAL_NAME_INFORMATION, FileName);
1867
1868         if( ulCopyLength > 0)
1869         {
1870
1871             if( bAddLeadingSlash)
1872             {
1873
1874                 Buffer->FileName[ cchCopied] = L'\\';
1875
1876                 ulCopyLength -= sizeof( WCHAR);
1877                 *Length -= sizeof( WCHAR);
1878                 cchCopied++;
1879             }
1880
1881             if( ulCopyLength >= pCcb->FullFileName.Length)
1882             {
1883
1884                 RtlCopyMemory( &Buffer->FileName[ cchCopied],
1885                                pCcb->FullFileName.Buffer,
1886                                pCcb->FullFileName.Length);
1887
1888                 ulCopyLength -= pCcb->FullFileName.Length;
1889                 *Length -= pCcb->FullFileName.Length;
1890                 cchCopied += pCcb->FullFileName.Length/sizeof( WCHAR);
1891             }
1892             else
1893             {
1894
1895                 RtlCopyMemory( &Buffer->FileName[ cchCopied],
1896                                pCcb->FullFileName.Buffer,
1897                                ulCopyLength);
1898
1899                 *Length -= ulCopyLength;
1900             }
1901         }
1902     }
1903     else
1904     {
1905
1906         ntStatus = STATUS_BUFFER_TOO_SMALL;
1907     }
1908
1909     return ntStatus;
1910 }
1911
1912 NTSTATUS
1913 AFSSetBasicInfo( IN PIRP Irp,
1914                  IN AFSDirectoryCB *DirectoryCB,
1915                  OUT BOOLEAN *bUpdateFileInfo)
1916 {
1917     NTSTATUS ntStatus = STATUS_SUCCESS;
1918     PFILE_BASIC_INFORMATION pBuffer;
1919     PIO_STACK_LOCATION pIrpSp = IoGetCurrentIrpStackLocation( Irp);
1920     ULONG ulNotifyFilter = 0;
1921     AFSCcb *pCcb = NULL;
1922
1923     __Enter
1924     {
1925
1926         pCcb = (AFSCcb *)pIrpSp->FileObject->FsContext2;
1927
1928         pBuffer = (PFILE_BASIC_INFORMATION)Irp->AssociatedIrp.SystemBuffer;
1929
1930         pCcb->FileUnwindInfo.FileAttributes = (ULONG)-1;
1931
1932         if( pBuffer->FileAttributes != (ULONGLONG)0)
1933         {
1934
1935             //
1936             // Make sure that the reparse point attribute is not modified.
1937             // Fail if the RP attribute is requested but it is not
1938             // already a RP.  Otherwise, ignore it.
1939             //
1940
1941             if ( !BooleanFlagOn( DirectoryCB->ObjectInformation->FileAttributes,
1942                                  FILE_ATTRIBUTE_REPARSE_POINT) &&
1943                  BooleanFlagOn( pBuffer->FileAttributes,
1944                                 FILE_ATTRIBUTE_REPARSE_POINT))
1945             {
1946
1947                 try_return( ntStatus = STATUS_INVALID_PARAMETER);
1948             }
1949
1950             //
1951             // Make sure that the directory attribute is not modified.
1952             // Fail if the D attribute is requested but it is not
1953             // already a directory.  Otherwise, ignore it.
1954             //
1955
1956             if ( !BooleanFlagOn( DirectoryCB->ObjectInformation->FileAttributes,
1957                                  FILE_ATTRIBUTE_DIRECTORY) &&
1958                  BooleanFlagOn( pBuffer->FileAttributes,
1959                                 FILE_ATTRIBUTE_DIRECTORY))
1960             {
1961
1962                 try_return( ntStatus = STATUS_INVALID_PARAMETER);
1963             }
1964
1965             //
1966             // Save the original value
1967             //
1968
1969             pCcb->FileUnwindInfo.FileAttributes = DirectoryCB->ObjectInformation->FileAttributes;
1970
1971             if( BooleanFlagOn( pBuffer->FileAttributes, FILE_ATTRIBUTE_READONLY))
1972             {
1973
1974                 //
1975                 // Set the readonly flag.
1976                 //
1977
1978                 if ( !BooleanFlagOn( DirectoryCB->ObjectInformation->FileAttributes,
1979                                      FILE_ATTRIBUTE_READONLY))
1980                 {
1981
1982                     if ( DirectoryCB->ObjectInformation->FileAttributes == FILE_ATTRIBUTE_NORMAL)
1983                     {
1984
1985                         DirectoryCB->ObjectInformation->FileAttributes = FILE_ATTRIBUTE_READONLY;
1986                     }
1987                     else
1988                     {
1989
1990                         DirectoryCB->ObjectInformation->FileAttributes |= FILE_ATTRIBUTE_READONLY;
1991                     }
1992
1993                     ulNotifyFilter |= FILE_NOTIFY_CHANGE_ATTRIBUTES;
1994
1995                     SetFlag( DirectoryCB->ObjectInformation->Fcb->Flags, AFS_FCB_FLAG_FILE_MODIFIED);
1996                 }
1997             }
1998             else
1999             {
2000                 //
2001                 // Reset the readonly flag.
2002                 //
2003
2004                 if ( BooleanFlagOn( DirectoryCB->ObjectInformation->FileAttributes,
2005                                     FILE_ATTRIBUTE_READONLY))
2006                 {
2007
2008                     DirectoryCB->ObjectInformation->FileAttributes &= ~FILE_ATTRIBUTE_READONLY;
2009
2010                     if ( DirectoryCB->ObjectInformation->FileAttributes == 0)
2011                     {
2012
2013                         DirectoryCB->ObjectInformation->FileAttributes = FILE_ATTRIBUTE_NORMAL;
2014                     }
2015
2016                     ulNotifyFilter |= FILE_NOTIFY_CHANGE_ATTRIBUTES;
2017
2018                     SetFlag( DirectoryCB->ObjectInformation->Fcb->Flags, AFS_FCB_FLAG_FILE_MODIFIED);
2019                 }
2020             }
2021         }
2022
2023         pCcb->FileUnwindInfo.CreationTime.QuadPart = (ULONGLONG)-1;
2024
2025         if( pBuffer->CreationTime.QuadPart != (ULONGLONG)-1 &&
2026             pBuffer->CreationTime.QuadPart != (ULONGLONG)0)
2027         {
2028
2029             pCcb->FileUnwindInfo.CreationTime.QuadPart = DirectoryCB->ObjectInformation->CreationTime.QuadPart;
2030
2031             DirectoryCB->ObjectInformation->CreationTime.QuadPart = pBuffer->CreationTime.QuadPart;
2032
2033             ulNotifyFilter |= FILE_NOTIFY_CHANGE_CREATION;
2034
2035             SetFlag( DirectoryCB->ObjectInformation->Fcb->Flags, AFS_FCB_FLAG_FILE_MODIFIED | AFS_FCB_FLAG_UPDATE_CREATE_TIME);
2036         }
2037
2038         pCcb->FileUnwindInfo.LastAccessTime.QuadPart = (ULONGLONG)-1;
2039
2040         if( pBuffer->LastAccessTime.QuadPart != (ULONGLONG)-1 &&
2041             pBuffer->LastAccessTime.QuadPart != (ULONGLONG)0)
2042         {
2043
2044             pCcb->FileUnwindInfo.LastAccessTime.QuadPart = DirectoryCB->ObjectInformation->LastAccessTime.QuadPart;
2045
2046             DirectoryCB->ObjectInformation->LastAccessTime.QuadPart = pBuffer->LastAccessTime.QuadPart;
2047
2048             ulNotifyFilter |= FILE_NOTIFY_CHANGE_LAST_ACCESS;
2049
2050             SetFlag( DirectoryCB->ObjectInformation->Fcb->Flags, AFS_FCB_FLAG_FILE_MODIFIED | AFS_FCB_FLAG_UPDATE_ACCESS_TIME);
2051         }
2052
2053         pCcb->FileUnwindInfo.LastWriteTime.QuadPart = (ULONGLONG)-1;
2054
2055         if( pBuffer->LastWriteTime.QuadPart != (ULONGLONG)-1 &&
2056             pBuffer->LastWriteTime.QuadPart != (ULONGLONG)0)
2057         {
2058
2059             pCcb->FileUnwindInfo.LastWriteTime.QuadPart = DirectoryCB->ObjectInformation->LastWriteTime.QuadPart;
2060
2061             DirectoryCB->ObjectInformation->LastWriteTime.QuadPart = pBuffer->LastWriteTime.QuadPart;
2062
2063             ulNotifyFilter |= FILE_NOTIFY_CHANGE_LAST_WRITE;
2064
2065             SetFlag( DirectoryCB->ObjectInformation->Fcb->Flags, AFS_FCB_FLAG_FILE_MODIFIED | AFS_FCB_FLAG_UPDATE_LAST_WRITE_TIME);
2066
2067             SetFlag( pCcb->Flags, CCB_FLAG_LAST_WRITE_TIME_SET);
2068
2069         } else if ( pBuffer->LastWriteTime.QuadPart == (ULONGLONG)-1) {
2070
2071             SetFlag( pCcb->Flags, CCB_FLAG_LAST_WRITE_TIME_SET);
2072         }
2073
2074         pCcb->FileUnwindInfo.ChangeTime.QuadPart = (ULONGLONG)-1;
2075
2076         if( pBuffer->ChangeTime.QuadPart != (ULONGLONG)-1 &&
2077             pBuffer->ChangeTime.QuadPart != (ULONGLONG)0)
2078         {
2079
2080             pCcb->FileUnwindInfo.ChangeTime.QuadPart = DirectoryCB->ObjectInformation->ChangeTime.QuadPart;
2081
2082             DirectoryCB->ObjectInformation->ChangeTime.QuadPart = pBuffer->ChangeTime.QuadPart;
2083
2084             ulNotifyFilter |= FILE_NOTIFY_CHANGE_LAST_ACCESS;
2085
2086             SetFlag( DirectoryCB->ObjectInformation->Fcb->Flags, AFS_FCB_FLAG_FILE_MODIFIED | AFS_FCB_FLAG_UPDATE_CHANGE_TIME);
2087         }
2088
2089         if( ulNotifyFilter > 0)
2090         {
2091
2092             *bUpdateFileInfo = TRUE;
2093
2094             if( BooleanFlagOn( DirectoryCB->ObjectInformation->Flags, AFS_OBJECT_FLAGS_PARENT_FID))
2095             {
2096
2097                 AFSObjectInfoCB * pParentObjectInfo = AFSFindObjectInfo( DirectoryCB->ObjectInformation->VolumeCB,
2098                                                                          &DirectoryCB->ObjectInformation->ParentFileId,
2099                                                                          TRUE);
2100
2101                 if ( pParentObjectInfo != NULL)
2102                 {
2103                     AFSFsRtlNotifyFullReportChange( pParentObjectInfo,
2104                                                     pCcb,
2105                                                     (ULONG)ulNotifyFilter,
2106                                                     (ULONG)FILE_ACTION_MODIFIED);
2107
2108                     AFSReleaseObjectInfo( &pParentObjectInfo);
2109                 }
2110             }
2111         }
2112
2113 try_exit:
2114
2115         NOTHING;
2116     }
2117
2118     return ntStatus;
2119 }
2120
2121 NTSTATUS
2122 AFSSetDispositionInfo( IN PIRP Irp,
2123                        IN AFSDirectoryCB *DirectoryCB)
2124 {
2125     NTSTATUS ntStatus = STATUS_SUCCESS;
2126     PFILE_DISPOSITION_INFORMATION pBuffer;
2127     PIO_STACK_LOCATION pIrpSp = IoGetCurrentIrpStackLocation( Irp);
2128     AFSFcb *pFcb = NULL;
2129     AFSCcb *pCcb = NULL;
2130
2131     __Enter
2132     {
2133
2134         pBuffer = (PFILE_DISPOSITION_INFORMATION)Irp->AssociatedIrp.SystemBuffer;
2135
2136         pFcb = (AFSFcb *)pIrpSp->FileObject->FsContext;
2137
2138         pCcb = (AFSCcb *)pIrpSp->FileObject->FsContext2;
2139
2140         //
2141         // Can't delete the root
2142         //
2143
2144         if( pFcb->Header.NodeTypeCode == AFS_ROOT_FCB)
2145         {
2146
2147             AFSDbgTrace(( AFS_SUBSYSTEM_FILE_PROCESSING,
2148                           AFS_TRACE_LEVEL_ERROR,
2149                           "AFSSetDispositionInfo Attempt to delete root entry\n"));
2150
2151             try_return( ntStatus = STATUS_CANNOT_DELETE);
2152         }
2153
2154         //
2155         // If the file is read only then do not allow the delete
2156         //
2157
2158         if( BooleanFlagOn( DirectoryCB->ObjectInformation->FileAttributes, FILE_ATTRIBUTE_READONLY))
2159         {
2160
2161             AFSDbgTrace(( AFS_SUBSYSTEM_FILE_PROCESSING,
2162                           AFS_TRACE_LEVEL_ERROR,
2163                           "AFSSetDispositionInfo Attempt to delete read only entry %wZ\n",
2164                           &DirectoryCB->NameInformation.FileName));
2165
2166             try_return( ntStatus = STATUS_CANNOT_DELETE);
2167         }
2168
2169         if( pBuffer->DeleteFile)
2170         {
2171
2172             //
2173             // Check if the caller can delete the file
2174             //
2175
2176             ntStatus = AFSNotifyDelete( DirectoryCB,
2177                                         &pCcb->AuthGroup,
2178                                         TRUE);
2179
2180             if( !NT_SUCCESS( ntStatus))
2181             {
2182
2183                 AFSDbgTrace(( AFS_SUBSYSTEM_FILE_PROCESSING,
2184                               AFS_TRACE_LEVEL_ERROR,
2185                               "AFSSetDispositionInfo Cannot delete entry %wZ Status %08lX\n",
2186                               &DirectoryCB->NameInformation.FileName,
2187                               ntStatus));
2188
2189                 try_return( ntStatus);
2190             }
2191
2192             if( pFcb->Header.NodeTypeCode == AFS_DIRECTORY_FCB)
2193             {
2194
2195                 //
2196                 // Reduce the Link count in the object information block
2197                 // to correspond with the deletion of the directory entry.
2198                 //
2199
2200                 pFcb->ObjectInformation->Links--;
2201
2202                 //
2203                 // Check if this is a directory that there are not currently other opens
2204                 //
2205
2206                 if( pFcb->ObjectInformation->Specific.Directory.ChildOpenHandleCount > 0)
2207                 {
2208
2209                     AFSDbgTrace(( AFS_SUBSYSTEM_FILE_PROCESSING,
2210                                   AFS_TRACE_LEVEL_ERROR,
2211                                   "AFSSetDispositionInfo Attempt to delete directory %wZ with open %u handles\n",
2212                                   &DirectoryCB->NameInformation.FileName,
2213                                   pFcb->ObjectInformation->Specific.Directory.ChildOpenHandleCount));
2214
2215                     try_return( ntStatus = STATUS_DIRECTORY_NOT_EMPTY);
2216                 }
2217
2218                 //
2219                 // Make sure the directory is enumerated before checking to see if it is empty.
2220                 //
2221
2222                 if( !BooleanFlagOn( pFcb->ObjectInformation->Flags, AFS_OBJECT_FLAGS_DIRECTORY_ENUMERATED))
2223                 {
2224
2225                     AFSAcquireExcl( pFcb->ObjectInformation->Specific.Directory.DirectoryNodeHdr.TreeLock,
2226                                     TRUE);
2227
2228                     if( !BooleanFlagOn( pFcb->ObjectInformation->Flags, AFS_OBJECT_FLAGS_DIRECTORY_ENUMERATED))
2229                     {
2230
2231                         AFSDbgTrace(( AFS_SUBSYSTEM_FILE_PROCESSING,
2232                                       AFS_TRACE_LEVEL_VERBOSE,
2233                                       "AFSSetDispositionInfo Enumerating parent FID %08lX-%08lX-%08lX-%08lX\n",
2234                                       pFcb->ObjectInformation->FileId.Cell,
2235                                       pFcb->ObjectInformation->FileId.Volume,
2236                                       pFcb->ObjectInformation->FileId.Vnode,
2237                                       pFcb->ObjectInformation->FileId.Unique));
2238
2239                         ntStatus = AFSEnumerateDirectory( &pCcb->AuthGroup,
2240                                                           pFcb->ObjectInformation,
2241                                                           TRUE);
2242
2243                         if( !NT_SUCCESS( ntStatus))
2244                         {
2245
2246                             AFSReleaseResource( pFcb->ObjectInformation->Specific.Directory.DirectoryNodeHdr.TreeLock);
2247
2248                             AFSDbgTrace(( AFS_SUBSYSTEM_FILE_PROCESSING,
2249                                           AFS_TRACE_LEVEL_ERROR,
2250                                           "AFSSetDispositionInfo Failed to enumerate parent FID %08lX-%08lX-%08lX-%08lX Status %08lX\n",
2251                                           pFcb->ObjectInformation->FileId.Cell,
2252                                           pFcb->ObjectInformation->FileId.Volume,
2253                                           pFcb->ObjectInformation->FileId.Vnode,
2254                                           pFcb->ObjectInformation->FileId.Unique,
2255                                           ntStatus));
2256
2257                             try_return( ntStatus);
2258                         }
2259                     }
2260
2261                     AFSReleaseResource( pFcb->ObjectInformation->Specific.Directory.DirectoryNodeHdr.TreeLock);
2262                 }
2263
2264                 if( !AFSIsDirectoryEmptyForDelete( pFcb))
2265                 {
2266
2267                     AFSDbgTrace(( AFS_SUBSYSTEM_FILE_PROCESSING,
2268                                   AFS_TRACE_LEVEL_ERROR,
2269                                   "AFSSetDispositionInfo Attempt to delete non-empty directory %wZ\n",
2270                                   &DirectoryCB->NameInformation.FileName));
2271
2272                     try_return( ntStatus = STATUS_DIRECTORY_NOT_EMPTY);
2273                 }
2274
2275                 AFSDbgTrace(( AFS_SUBSYSTEM_FILE_PROCESSING,
2276                               AFS_TRACE_LEVEL_VERBOSE,
2277                               "AFSSetDispositionInfo Setting PENDING_DELETE on DirEntry  %p Name %wZ\n",
2278                               DirectoryCB,
2279                               &DirectoryCB->NameInformation.FileName));
2280
2281                 SetFlag( pCcb->DirectoryCB->Flags, AFS_DIR_ENTRY_PENDING_DELETE);
2282             }
2283             else if( pFcb->Header.NodeTypeCode == AFS_FILE_FCB)
2284             {
2285                 BOOLEAN bMmFlushed;
2286
2287                 AFSDbgTrace(( AFS_SUBSYSTEM_LOCK_PROCESSING,
2288                               AFS_TRACE_LEVEL_VERBOSE,
2289                               "AFSSetDispositionInfo Acquiring Fcb lock %p EXCL %08lX\n",
2290                               &pFcb->NPFcb->Resource,
2291                               PsGetCurrentThread()));
2292
2293                 AFSAcquireExcl( &pFcb->NPFcb->Resource,
2294                                 TRUE);
2295
2296                 AFSDbgTrace(( AFS_SUBSYSTEM_LOCK_PROCESSING|AFS_SUBSYSTEM_SECTION_OBJECT,
2297                               AFS_TRACE_LEVEL_VERBOSE,
2298                               "AFSSetDispositionInfo Acquiring Fcb SectionObject lock %p EXCL %08lX\n",
2299                               &pFcb->NPFcb->SectionObjectResource,
2300                               PsGetCurrentThread()));
2301
2302                 AFSAcquireExcl( &pFcb->NPFcb->SectionObjectResource,
2303                                 TRUE);
2304
2305                 __try
2306                 {
2307
2308                     //
2309                     // Attempt to flush any outstanding data
2310                     //
2311
2312                     bMmFlushed = MmFlushImageSection( &pFcb->NPFcb->SectionObjectPointers,
2313                                                       MmFlushForDelete);
2314
2315                     if ( bMmFlushed)
2316                     {
2317
2318                         //
2319                         // Set PENDING_DELETE before CcPurgeCacheSection to avoid a
2320                         // deadlock with Trend Micro's Enterprise anti-virus product
2321                         // which attempts to open the file which is being deleted.
2322                         //
2323
2324                         AFSDbgTrace(( AFS_SUBSYSTEM_FILE_PROCESSING,
2325                                       AFS_TRACE_LEVEL_VERBOSE,
2326                                       "AFSSetDispositionInfo Setting PENDING_DELETE on DirEntry %p Name %wZ\n",
2327                                       DirectoryCB,
2328                                       &DirectoryCB->NameInformation.FileName));
2329
2330                         SetFlag( pCcb->DirectoryCB->Flags, AFS_DIR_ENTRY_PENDING_DELETE);
2331
2332                         //
2333                         // Purge the cache as well
2334                         //
2335
2336                         if( pFcb->NPFcb->SectionObjectPointers.DataSectionObject != NULL)
2337                         {
2338
2339                             if ( !CcPurgeCacheSection( &pFcb->NPFcb->SectionObjectPointers,
2340                                                        NULL,
2341                                                        0,
2342                                                        TRUE))
2343                             {
2344
2345                                 SetFlag( pFcb->Flags, AFS_FCB_FLAG_PURGE_ON_CLOSE);
2346                             }
2347                         }
2348                     }
2349                 }
2350                 __except( EXCEPTION_EXECUTE_HANDLER)
2351                 {
2352
2353                     bMmFlushed = FALSE;
2354
2355                     ntStatus = GetExceptionCode();
2356
2357                     AFSDbgTrace(( 0,
2358                                   0,
2359                                   "EXCEPTION - AFSSetDispositionInfo MmFlushImageSection failed FID %08lX-%08lX-%08lX-%08lX Status 0x%08lX\n",
2360                                   pFcb->ObjectInformation->FileId.Cell,
2361                                   pFcb->ObjectInformation->FileId.Volume,
2362                                   pFcb->ObjectInformation->FileId.Vnode,
2363                                   pFcb->ObjectInformation->FileId.Unique,
2364                                   ntStatus));
2365                 }
2366
2367                 AFSDbgTrace(( AFS_SUBSYSTEM_LOCK_PROCESSING|AFS_SUBSYSTEM_SECTION_OBJECT,
2368                               AFS_TRACE_LEVEL_VERBOSE,
2369                               "AFSSetDispositionInfo Releasing Fcb SectionObject lock %p EXCL %08lX\n",
2370                               &pFcb->NPFcb->SectionObjectResource,
2371                               PsGetCurrentThread()));
2372
2373                 AFSReleaseResource( &pFcb->NPFcb->SectionObjectResource);
2374
2375                 AFSDbgTrace(( AFS_SUBSYSTEM_LOCK_PROCESSING,
2376                               AFS_TRACE_LEVEL_VERBOSE,
2377                               "AFSSetDispositionInfo Releasing Fcb lock %p EXCL %08lX\n",
2378                               &pFcb->NPFcb->Resource,
2379                               PsGetCurrentThread()));
2380
2381                 AFSReleaseResource( &pFcb->NPFcb->Resource);
2382
2383                 if ( !bMmFlushed)
2384                 {
2385
2386                     AFSDbgTrace(( AFS_SUBSYSTEM_FILE_PROCESSING,
2387                                   AFS_TRACE_LEVEL_ERROR,
2388                                   "AFSSetDispositionInfo Failed to flush image section for delete Entry %wZ\n",
2389                                   &DirectoryCB->NameInformation.FileName));
2390
2391                     try_return( ntStatus = STATUS_CANNOT_DELETE);
2392                 }
2393             }
2394             else if( pFcb->Header.NodeTypeCode == AFS_SYMBOLIC_LINK_FCB ||
2395                      pFcb->Header.NodeTypeCode == AFS_MOUNT_POINT_FCB ||
2396                      pFcb->Header.NodeTypeCode == AFS_DFS_LINK_FCB ||
2397                      pFcb->Header.NodeTypeCode == AFS_INVALID_FCB)
2398             {
2399
2400                 AFSDbgTrace(( AFS_SUBSYSTEM_FILE_PROCESSING,
2401                               AFS_TRACE_LEVEL_VERBOSE,
2402                               "AFSSetDispositionInfo Setting PENDING_DELETE on DirEntry %p Name %wZ\n",
2403                               DirectoryCB,
2404                               &DirectoryCB->NameInformation.FileName));
2405
2406                 SetFlag( pCcb->DirectoryCB->Flags, AFS_DIR_ENTRY_PENDING_DELETE);
2407             }
2408         }
2409         else
2410         {
2411
2412             ClearFlag( pCcb->DirectoryCB->Flags, AFS_DIR_ENTRY_PENDING_DELETE);
2413         }
2414
2415         //
2416         // OK, should be good to go, set the flag in the file object
2417         //
2418
2419         pIrpSp->FileObject->DeletePending = pBuffer->DeleteFile;
2420
2421 try_exit:
2422
2423         NOTHING;
2424     }
2425
2426     return ntStatus;
2427 }
2428
2429 NTSTATUS
2430 AFSSetFileLinkInfo( IN PIRP Irp)
2431 {
2432
2433     NTSTATUS ntStatus = STATUS_SUCCESS;
2434     AFSDeviceExt *pDeviceExt = (AFSDeviceExt *)AFSRDRDeviceObject->DeviceExtension;
2435     PIO_STACK_LOCATION pIrpSp = IoGetCurrentIrpStackLocation( Irp);
2436     PFILE_LINK_INFORMATION pFileLinkInfo = NULL;
2437     PFILE_OBJECT pSrcFileObj = NULL;
2438     PFILE_OBJECT pTargetFileObj = pIrpSp->Parameters.SetFile.FileObject;
2439     AFSFcb *pSrcFcb = NULL, *pTargetDcb = NULL;
2440     AFSCcb *pSrcCcb = NULL, *pTargetDirCcb = NULL;
2441     AFSObjectInfoCB *pSrcObject = NULL;
2442     AFSObjectInfoCB *pSrcParentObject = NULL, *pTargetParentObject = NULL;
2443     UNICODE_STRING uniSourceName, uniTargetName;
2444     UNICODE_STRING uniFullTargetName, uniTargetParentName;
2445     BOOLEAN bCommonParent = FALSE;
2446     AFSDirectoryCB *pTargetDirEntry = NULL;
2447     AFSDirectoryCB *pNewTargetDirEntry = NULL;
2448     ULONG ulTargetCRC;
2449     BOOLEAN bTargetEntryExists = FALSE;
2450     LONG lCount;
2451     BOOLEAN bReleaseTargetDirLock = FALSE;
2452     ULONG ulNotificationAction = 0, ulNotifyFilter = 0;
2453
2454     __Enter
2455     {
2456
2457         pSrcFileObj = pIrpSp->FileObject;
2458
2459         pSrcFcb = (AFSFcb *)pSrcFileObj->FsContext;
2460         pSrcCcb = (AFSCcb *)pSrcFileObj->FsContext2;
2461
2462         pSrcObject = pSrcFcb->ObjectInformation;
2463
2464         if ( BooleanFlagOn( pSrcObject->Flags, AFS_OBJECT_FLAGS_PARENT_FID))
2465         {
2466
2467             pSrcParentObject = AFSFindObjectInfo( pSrcObject->VolumeCB,
2468                                                   &pSrcObject->ParentFileId,
2469                                                   TRUE);
2470         }
2471
2472         if( pSrcParentObject == NULL)
2473         {
2474
2475             AFSDbgTrace(( AFS_SUBSYSTEM_FILE_PROCESSING,
2476                           AFS_TRACE_LEVEL_ERROR,
2477                           "AFSSetFileLinkInfo Unable to resolve SrcParentObject (INVALID_PARAMETER)\n"));
2478
2479             ASSERT( FALSE);
2480
2481             try_return( ntStatus = STATUS_INVALID_PARAMETER);
2482         }
2483
2484         pFileLinkInfo = (PFILE_LINK_INFORMATION)Irp->AssociatedIrp.SystemBuffer;
2485
2486         //
2487         // Perform some basic checks to ensure FS integrity
2488         //
2489
2490         if( pSrcFcb->Header.NodeTypeCode != AFS_FILE_FCB)
2491         {
2492
2493             AFSDbgTrace(( AFS_SUBSYSTEM_FILE_PROCESSING,
2494                           AFS_TRACE_LEVEL_ERROR,
2495                           "AFSSetFileLinkInfo Attempt to non-file (INVALID_PARAMETER)\n"));
2496
2497             try_return( ntStatus = STATUS_INVALID_PARAMETER);
2498         }
2499
2500         if( pTargetFileObj == NULL)
2501         {
2502
2503             if ( pFileLinkInfo->RootDirectory)
2504             {
2505
2506                 //
2507                 // The target directory is provided by HANDLE
2508                 // RootDirectory is only set when the target directory is not the same
2509                 // as the source directory.
2510                 //
2511                 // AFS only supports hard links within a single directory.
2512                 //
2513                 // The IOManager should translate any Handle to a FileObject for us.
2514                 // However, the failure to receive a FileObject is treated as a fatal
2515                 // error.
2516                 //
2517
2518                 AFSDbgTrace(( AFS_SUBSYSTEM_FILE_PROCESSING,
2519                               AFS_TRACE_LEVEL_ERROR,
2520                               "AFSSetFileLinkInfo Attempt to link %wZ to alternate directory by handle INVALID_PARAMETER\n",
2521                               &pSrcCcb->DirectoryCB->NameInformation.FileName));
2522
2523                 try_return( ntStatus = STATUS_INVALID_PARAMETER);
2524             }
2525             else
2526             {
2527
2528                 uniFullTargetName.Length = (USHORT)pFileLinkInfo->FileNameLength;
2529
2530                 uniFullTargetName.Buffer = (PWSTR)&pFileLinkInfo->FileName;
2531
2532                 AFSRetrieveFinalComponent( &uniFullTargetName,
2533                                            &uniTargetName);
2534
2535                 AFSRetrieveParentPath( &uniFullTargetName,
2536                                        &uniTargetParentName);
2537
2538                 if ( uniTargetParentName.Length == 0)
2539                 {
2540
2541                     //
2542                     // This is a simple rename. Here the target directory is the same as the source parent directory
2543                     // and the name is retrieved from the system buffer information
2544                     //
2545
2546                     pTargetParentObject = pSrcParentObject;
2547                 }
2548                 else
2549                 {
2550                     //
2551                     // uniTargetParentName contains the directory the renamed object
2552                     // will be moved to.  Must obtain the TargetParentObject.
2553                     //
2554
2555                     AFSDbgTrace(( AFS_SUBSYSTEM_FILE_PROCESSING,
2556                                   AFS_TRACE_LEVEL_ERROR,
2557                                   "AFSSetFileLinkInfo Attempt to link  %wZ to alternate directory %wZ (NOT_SAME_DEVICE)\n",
2558                                   &pSrcCcb->DirectoryCB->NameInformation.FileName,
2559                                   &uniFullTargetName));
2560
2561                     try_return( ntStatus = STATUS_NOT_SAME_DEVICE);
2562                 }
2563             }
2564
2565             pTargetDcb = pTargetParentObject->Fcb;
2566         }
2567         else
2568         {
2569
2570             //
2571             // So here we have the target directory taken from the targetfile object
2572             //
2573
2574             pTargetDcb = (AFSFcb *)pTargetFileObj->FsContext;
2575
2576             pTargetDirCcb = (AFSCcb *)pTargetFileObj->FsContext2;
2577
2578             pTargetParentObject = (AFSObjectInfoCB *)pTargetDcb->ObjectInformation;
2579
2580             //
2581             // Grab the target name which we setup in the IRP_MJ_CREATE handler. By how we set this up
2582             // it is only the target component of the rename operation
2583             //
2584
2585             uniTargetName = *((PUNICODE_STRING)&pTargetFileObj->FileName);
2586         }
2587
2588         //
2589         // The quick check to see if they are self linking.
2590         // Do the names match? Only do this where the parent directories are
2591         // the same
2592         //
2593
2594         if( pTargetParentObject == pSrcParentObject)
2595         {
2596
2597             if( FsRtlAreNamesEqual( &uniTargetName,
2598                                     &uniSourceName,
2599                                     FALSE,
2600                                     NULL))
2601             {
2602                 try_return( ntStatus = STATUS_SUCCESS);
2603             }
2604
2605             bCommonParent = TRUE;
2606         }
2607         else
2608         {
2609
2610             //
2611             // We do not allow cross-volume hard links
2612             //
2613
2614             if( pTargetParentObject->VolumeCB != pSrcObject->VolumeCB)
2615             {
2616
2617                 AFSDbgTrace(( AFS_SUBSYSTEM_FILE_PROCESSING,
2618                               AFS_TRACE_LEVEL_ERROR,
2619                               "AFSSetFileLinkInfo Attempt to link to different volume %wZ\n",
2620                               &pSrcCcb->DirectoryCB->NameInformation.FileName));
2621
2622                 try_return( ntStatus = STATUS_NOT_SAME_DEVICE);
2623             }
2624         }
2625
2626         ulTargetCRC = AFSGenerateCRC( &uniTargetName,
2627                                       FALSE);
2628
2629         AFSAcquireExcl( pTargetParentObject->Specific.Directory.DirectoryNodeHdr.TreeLock,
2630                         TRUE);
2631
2632         bReleaseTargetDirLock = TRUE;
2633
2634         AFSLocateCaseSensitiveDirEntry( pTargetParentObject->Specific.Directory.DirectoryNodeHdr.CaseSensitiveTreeHead,
2635                                         ulTargetCRC,
2636                                         &pTargetDirEntry);
2637
2638         if( pTargetDirEntry == NULL)
2639         {
2640
2641             //
2642             // Missed so perform a case insensitive lookup
2643             //
2644
2645             ulTargetCRC = AFSGenerateCRC( &uniTargetName,
2646                                           TRUE);
2647
2648             AFSLocateCaseInsensitiveDirEntry( pTargetParentObject->Specific.Directory.DirectoryNodeHdr.CaseInsensitiveTreeHead,
2649                                               ulTargetCRC,
2650                                               &pTargetDirEntry);
2651         }
2652
2653         if ( !BooleanFlagOn( pDeviceExt->DeviceFlags, AFS_DEVICE_FLAG_DISABLE_SHORTNAMES) &&
2654              pTargetDirEntry == NULL && RtlIsNameLegalDOS8Dot3( &uniTargetName,
2655                                                                 NULL,
2656                                                                 NULL))
2657         {
2658             //
2659             // Try the short name
2660             //
2661             AFSLocateShortNameDirEntry( pTargetParentObject->Specific.Directory.ShortNameTree,
2662                                         ulTargetCRC,
2663                                         &pTargetDirEntry);
2664         }
2665
2666         //
2667         // Increment our ref count on the dir entry
2668         //
2669
2670         if( pTargetDirEntry != NULL)
2671         {
2672
2673             ASSERT( BooleanFlagOn( pTargetDirEntry->ObjectInformation->Flags, AFS_OBJECT_FLAGS_PARENT_FID) &&
2674                     AFSIsEqualFID( &pTargetParentObject->FileId, &pTargetDirEntry->ObjectInformation->ParentFileId));
2675
2676             lCount = InterlockedIncrement( &pTargetDirEntry->DirOpenReferenceCount);
2677
2678             AFSDbgTrace(( AFS_SUBSYSTEM_DIRENTRY_REF_COUNTING,
2679                           AFS_TRACE_LEVEL_VERBOSE,
2680                           "AFSSetFileLinkInfo Increment count on %wZ DE %p Ccb %p Cnt %d\n",
2681                           &pTargetDirEntry->NameInformation.FileName,
2682                           pTargetDirEntry,
2683                           pSrcCcb,
2684                           lCount));
2685
2686             ASSERT( lCount >= 0);
2687
2688             if( !pFileLinkInfo->ReplaceIfExists)
2689             {
2690
2691                 AFSDbgTrace(( AFS_SUBSYSTEM_FILE_PROCESSING,
2692                               AFS_TRACE_LEVEL_ERROR,
2693                               "AFSSetFileLinkInfo Attempt to link with target collision %wZ Target %wZ\n",
2694                               &pSrcCcb->DirectoryCB->NameInformation.FileName,
2695                               &pTargetDirEntry->NameInformation.FileName));
2696
2697                 try_return( ntStatus = STATUS_OBJECT_NAME_COLLISION);
2698             }
2699
2700             AFSDbgTrace(( AFS_SUBSYSTEM_FILE_PROCESSING | AFS_SUBSYSTEM_DIRENTRY_REF_COUNTING,
2701                           AFS_TRACE_LEVEL_ERROR,
2702                           "AFSSetFileLinkInfo Target %wZ exists DE %p Count %d, performing delete of target\n",
2703                           &pTargetDirEntry->NameInformation.FileName,
2704                           pTargetDirEntry,
2705                           lCount));
2706
2707             //
2708             // Pull the directory entry from the parent
2709             //
2710
2711             AFSRemoveDirNodeFromParent( pTargetParentObject,
2712                                         pTargetDirEntry,
2713                                         FALSE);
2714
2715             bTargetEntryExists = TRUE;
2716         }
2717         else
2718         {
2719             AFSDbgTrace(( AFS_SUBSYSTEM_FILE_PROCESSING,
2720                           AFS_TRACE_LEVEL_VERBOSE,
2721                           "AFSSetFileLinkInfo Target does NOT exist, normal linking\n"));
2722         }
2723
2724         //
2725         // OK, this is a simple rename. Issue the rename
2726         // request to the service.
2727         //
2728
2729         ntStatus = AFSNotifyHardLink( pSrcObject,
2730                                       &pSrcCcb->AuthGroup,
2731                                       pSrcParentObject,
2732                                       pTargetDcb->ObjectInformation,
2733                                       pSrcCcb->DirectoryCB,
2734                                       &uniTargetName,
2735                                       pFileLinkInfo->ReplaceIfExists,
2736                                       &pNewTargetDirEntry);
2737
2738         if( ntStatus != STATUS_REPARSE &&
2739             !NT_SUCCESS( ntStatus))
2740         {
2741
2742             AFSDbgTrace(( AFS_SUBSYSTEM_FILE_PROCESSING,
2743                           AFS_TRACE_LEVEL_ERROR,
2744                           "AFSSetFileLinkInfo Failed link of %wZ to target %wZ Status %08lX\n",
2745                           &pSrcCcb->DirectoryCB->NameInformation.FileName,
2746                           &uniTargetName,
2747                           ntStatus));
2748
2749             try_return( ntStatus);
2750         }
2751
2752         if ( ntStatus != STATUS_REPARSE)
2753         {
2754
2755             AFSInsertDirectoryNode( pTargetDcb->ObjectInformation,
2756                                     pNewTargetDirEntry,
2757                                     TRUE);
2758         }
2759
2760         //
2761         // Send notification for the target link file
2762         //
2763
2764         if( bTargetEntryExists || pNewTargetDirEntry)
2765         {
2766
2767             ulNotificationAction = FILE_ACTION_MODIFIED;
2768         }
2769         else
2770         {
2771
2772             ulNotificationAction = FILE_ACTION_ADDED;
2773         }
2774
2775         AFSFsRtlNotifyFullReportChange( pTargetParentObject,
2776                                         pSrcCcb,
2777                                         (ULONG)ulNotifyFilter,
2778                                         (ULONG)ulNotificationAction);
2779
2780       try_exit:
2781
2782         if( !NT_SUCCESS( ntStatus))
2783         {
2784
2785             if( bTargetEntryExists)
2786             {
2787
2788                 AFSInsertDirectoryNode( pTargetParentObject,
2789                                         pTargetDirEntry,
2790                                         FALSE);
2791             }
2792         }
2793
2794         if( pTargetDirEntry != NULL)
2795         {
2796
2797             //
2798             // Release DirOpenReferenceCount obtained above
2799             //
2800
2801             lCount = InterlockedDecrement( &pTargetDirEntry->DirOpenReferenceCount);
2802
2803             AFSDbgTrace(( AFS_SUBSYSTEM_DIRENTRY_REF_COUNTING,
2804                           AFS_TRACE_LEVEL_VERBOSE,
2805                           "AFSSetFileLinkInfo Decrement count on %wZ DE %p Ccb %p Cnt %d\n",
2806                           &pTargetDirEntry->NameInformation.FileName,
2807                           pTargetDirEntry,
2808                           pSrcCcb,
2809                           lCount));
2810
2811             ASSERT( lCount >= 0);
2812         }
2813
2814         if( pNewTargetDirEntry != NULL)
2815         {
2816
2817             //
2818             // Release DirOpenReferenceCount obtained from AFSNotifyHardLink
2819             //
2820
2821             lCount = InterlockedDecrement( &pNewTargetDirEntry->DirOpenReferenceCount);
2822
2823             AFSDbgTrace(( AFS_SUBSYSTEM_DIRENTRY_REF_COUNTING,
2824                           AFS_TRACE_LEVEL_VERBOSE,
2825                           "AFSSetFileLinkInfo Decrement count on %wZ DE %p Ccb %p Cnt %d\n",
2826                           &pNewTargetDirEntry->NameInformation.FileName,
2827                           pNewTargetDirEntry,
2828                           pSrcCcb,
2829                           lCount));
2830
2831             ASSERT( lCount >= 0);
2832         }
2833
2834         if( bReleaseTargetDirLock)
2835         {
2836
2837             AFSReleaseResource( pTargetParentObject->Specific.Directory.DirectoryNodeHdr.TreeLock);
2838         }
2839
2840         if ( pSrcParentObject != NULL)
2841         {
2842
2843             AFSReleaseObjectInfo( &pSrcParentObject);
2844         }
2845
2846         //
2847         // No need to release pTargetParentObject as it is either a copy of pSrcParentObject
2848         // or (AFSFcb *)pTargetFileObj->FsContext->ObjectInformation
2849         //
2850
2851         pTargetParentObject = NULL;
2852     }
2853
2854     return ntStatus;
2855 }
2856
2857 NTSTATUS
2858 AFSSetRenameInfo( IN PIRP Irp)
2859 {
2860
2861     NTSTATUS ntStatus = STATUS_SUCCESS;
2862     AFSDeviceExt *pDeviceExt = (AFSDeviceExt *)AFSRDRDeviceObject->DeviceExtension;
2863     PIO_STACK_LOCATION pIrpSp = IoGetCurrentIrpStackLocation( Irp);
2864     AFSFcb *pSrcFcb = NULL, *pTargetDcb = NULL, *pTargetFcb = NULL;
2865     AFSCcb *pSrcCcb = NULL, *pTargetDirCcb = NULL;
2866     PFILE_OBJECT pSrcFileObj = pIrpSp->FileObject;
2867     PFILE_OBJECT pTargetFileObj = pIrpSp->Parameters.SetFile.FileObject;
2868     PFILE_OBJECT pTargetParentFileObj = NULL;
2869     PFILE_RENAME_INFORMATION pRenameInfo = NULL;
2870     UNICODE_STRING uniTargetName, uniSourceName, uniTargetParentName;
2871     BOOLEAN bReplaceIfExists = FALSE;
2872     UNICODE_STRING uniShortName;
2873     AFSDirectoryCB *pTargetDirEntry = NULL;
2874     ULONG ulTargetCRC = 0;
2875     BOOLEAN bTargetEntryExists = FALSE;
2876     AFSObjectInfoCB *pSrcObject = NULL;
2877     AFSObjectInfoCB *pSrcParentObject = NULL, *pTargetParentObject = NULL;
2878     AFSFileID stNewFid;
2879     ULONG ulNotificationAction = 0, ulNotifyFilter = 0;
2880     UNICODE_STRING uniFullTargetName;
2881     BOOLEAN bCommonParent = FALSE;
2882     BOOLEAN bReleaseTargetDirLock = FALSE;
2883     BOOLEAN bReleaseSourceDirLock = FALSE;
2884     BOOLEAN bDereferenceTargetParentObject = FALSE;
2885     PERESOURCE  pSourceDirLock = NULL;
2886     LONG lCount;
2887
2888     __Enter
2889     {
2890
2891         bReplaceIfExists = pIrpSp->Parameters.SetFile.ReplaceIfExists;
2892
2893         pRenameInfo = (PFILE_RENAME_INFORMATION)Irp->AssociatedIrp.SystemBuffer;
2894
2895         pSrcFcb = (AFSFcb *)pSrcFileObj->FsContext;
2896         pSrcCcb = (AFSCcb *)pSrcFileObj->FsContext2;
2897
2898         pSrcObject = pSrcFcb->ObjectInformation;
2899
2900         if ( BooleanFlagOn( pSrcObject->Flags, AFS_OBJECT_FLAGS_PARENT_FID))
2901         {
2902
2903             pSrcParentObject = AFSFindObjectInfo( pSrcObject->VolumeCB,
2904                                                   &pSrcObject->ParentFileId,
2905                                                   TRUE);
2906         }
2907
2908         if( pSrcParentObject == NULL)
2909         {
2910
2911             AFSDbgTrace(( AFS_SUBSYSTEM_FILE_PROCESSING,
2912                           AFS_TRACE_LEVEL_ERROR,
2913                           "AFSSetRenameInfo Unable to resolve SrcParentObject (INVALID_PARAMETER)\n"));
2914
2915             ASSERT( FALSE);
2916
2917             try_return( ntStatus = STATUS_INVALID_PARAMETER);
2918         }
2919
2920         //
2921         // Perform some basic checks to ensure FS integrity
2922         //
2923
2924         if( pSrcFcb->Header.NodeTypeCode == AFS_ROOT_FCB)
2925         {
2926
2927             //
2928             // Can't rename the root directory
2929             //
2930
2931             AFSDbgTrace(( AFS_SUBSYSTEM_FILE_PROCESSING,
2932                           AFS_TRACE_LEVEL_ERROR,
2933                           "AFSSetRenameInfo Attempt to rename root entry\n"));
2934
2935             try_return( ntStatus = STATUS_INVALID_PARAMETER);
2936         }
2937
2938         if( pSrcFcb->Header.NodeTypeCode == AFS_DIRECTORY_FCB)
2939         {
2940
2941             //
2942             // If there are any open children then fail the rename
2943             //
2944
2945             if( pSrcObject->Specific.Directory.ChildOpenHandleCount > 0)
2946             {
2947
2948                 AFSDbgTrace(( AFS_SUBSYSTEM_FILE_PROCESSING,
2949                               AFS_TRACE_LEVEL_ERROR,
2950                               "AFSSetRenameInfo Attempt to rename directory with open children %wZ\n",
2951                               &pSrcCcb->DirectoryCB->NameInformation.FileName));
2952
2953                 try_return( ntStatus = STATUS_ACCESS_DENIED);
2954             }
2955         }
2956
2957
2958         //
2959         // Extract off the final component name from the Fcb
2960         //
2961
2962         uniSourceName.Length = (USHORT)pSrcCcb->DirectoryCB->NameInformation.FileName.Length;
2963         uniSourceName.MaximumLength = uniSourceName.Length;
2964
2965         uniSourceName.Buffer = pSrcCcb->DirectoryCB->NameInformation.FileName.Buffer;
2966
2967         //
2968         // Resolve the target fileobject
2969         //
2970
2971         if( pTargetFileObj == NULL)
2972         {
2973
2974             if ( pRenameInfo->RootDirectory)
2975             {
2976
2977                 AFSDbgTrace(( AFS_SUBSYSTEM_FILE_PROCESSING,
2978                               AFS_TRACE_LEVEL_ERROR,
2979                               "AFSSetRenameInfo Handle provided but no FileObject ntStatus INVALID_PARAMETER\n"));
2980
2981                 try_return( ntStatus = STATUS_INVALID_PARAMETER);
2982             }
2983             else
2984             {
2985
2986                 uniFullTargetName.Length = (USHORT)pRenameInfo->FileNameLength;
2987
2988                 uniFullTargetName.Buffer = (PWSTR)&pRenameInfo->FileName;
2989
2990                 AFSRetrieveFinalComponent( &uniFullTargetName,
2991                                            &uniTargetName);
2992
2993                 AFSRetrieveParentPath( &uniFullTargetName,
2994                                        &uniTargetParentName);
2995
2996                 if ( uniTargetParentName.Length == 0)
2997                 {
2998
2999                     //
3000                     // This is a simple rename. Here the target directory is the same as the source parent directory
3001                     // and the name is retrieved from the system buffer information
3002                     //
3003
3004                     pTargetParentObject = pSrcParentObject;
3005                 }
3006                 else
3007                 {
3008                     //
3009                     // uniTargetParentName contains the directory the renamed object
3010                     // will be moved to.  Must obtain the TargetParentObject.
3011                     //
3012
3013                     AFSDbgTrace(( AFS_SUBSYSTEM_FILE_PROCESSING,
3014                                   AFS_TRACE_LEVEL_ERROR,
3015                                   "AFSSetRenameInfo Attempt to move %wZ to %wZ -- not yet supported (NOT_SAME_DEVICE)\n",
3016                                   &pSrcCcb->DirectoryCB->NameInformation.FileName,
3017                                   &uniFullTargetName));
3018
3019                     try_return( ntStatus = STATUS_NOT_SAME_DEVICE);
3020                 }
3021             }
3022
3023             pTargetDcb = pTargetParentObject->Fcb;
3024         }
3025         else
3026         {
3027
3028             //
3029             // So here we have the target directory taken from the targetfile object
3030             //
3031
3032             pTargetDcb = (AFSFcb *)pTargetFileObj->FsContext;
3033
3034             pTargetDirCcb = (AFSCcb *)pTargetFileObj->FsContext2;
3035
3036             pTargetParentObject = (AFSObjectInfoCB *)pTargetDcb->ObjectInformation;
3037
3038             //
3039             // Grab the target name which we setup in the IRP_MJ_CREATE handler. By how we set this up
3040             // it is only the target component of the rename operation
3041             //
3042
3043             uniTargetName = *((PUNICODE_STRING)&pTargetFileObj->FileName);
3044         }
3045
3046         //
3047         // The quick check to see if they are not really performing a rename
3048         // Do the names match? Only do this where the parent directories are
3049         // the same
3050         //
3051
3052         if( pTargetParentObject == pSrcParentObject)
3053         {
3054
3055             if( FsRtlAreNamesEqual( &uniTargetName,
3056                                     &uniSourceName,
3057                                     FALSE,
3058                                     NULL))
3059             {
3060                 try_return( ntStatus = STATUS_SUCCESS);
3061             }
3062
3063             bCommonParent = TRUE;
3064         }
3065         else
3066         {
3067
3068             bCommonParent = FALSE;
3069         }
3070
3071         //
3072         // We do not allow cross-volume renames to occur
3073         //
3074
3075         if( pTargetParentObject->VolumeCB != pSrcObject->VolumeCB)
3076         {
3077
3078             AFSDbgTrace(( AFS_SUBSYSTEM_FILE_PROCESSING,
3079                           AFS_TRACE_LEVEL_ERROR,
3080                           "AFSSetRenameInfo Attempt to rename directory to different volume %wZ\n",
3081                           &pSrcCcb->DirectoryCB->NameInformation.FileName));
3082
3083             try_return( ntStatus = STATUS_NOT_SAME_DEVICE);
3084         }
3085
3086         ulTargetCRC = AFSGenerateCRC( &uniTargetName,
3087                                       FALSE);
3088
3089         AFSAcquireExcl( pTargetParentObject->Specific.Directory.DirectoryNodeHdr.TreeLock,
3090                         TRUE);
3091
3092         bReleaseTargetDirLock = TRUE;
3093
3094         if( pTargetParentObject != pSrcParentObject)
3095         {
3096             AFSAcquireExcl( pSrcParentObject->Specific.Directory.DirectoryNodeHdr.TreeLock,
3097                             TRUE);
3098
3099             bReleaseSourceDirLock = TRUE;
3100
3101             pSourceDirLock = pSrcParentObject->Specific.Directory.DirectoryNodeHdr.TreeLock;
3102         }
3103
3104         AFSLocateCaseSensitiveDirEntry( pTargetParentObject->Specific.Directory.DirectoryNodeHdr.CaseSensitiveTreeHead,
3105                                         ulTargetCRC,
3106                                         &pTargetDirEntry);
3107
3108         if( pTargetDirEntry == NULL)
3109         {
3110
3111             //
3112             // Missed so perform a case insensitive lookup
3113             //
3114
3115             ulTargetCRC = AFSGenerateCRC( &uniTargetName,
3116                                           TRUE);
3117
3118             AFSLocateCaseInsensitiveDirEntry( pTargetParentObject->Specific.Directory.DirectoryNodeHdr.CaseInsensitiveTreeHead,
3119                                               ulTargetCRC,
3120                                               &pTargetDirEntry);
3121         }
3122
3123         if ( !BooleanFlagOn( pDeviceExt->DeviceFlags, AFS_DEVICE_FLAG_DISABLE_SHORTNAMES) &&
3124              pTargetDirEntry == NULL && RtlIsNameLegalDOS8Dot3( &uniTargetName,
3125                                                                NULL,
3126                                                                NULL))
3127         {
3128             //
3129             // Try the short name
3130             //
3131             AFSLocateShortNameDirEntry( pTargetParentObject->Specific.Directory.ShortNameTree,
3132                                         ulTargetCRC,
3133                                         &pTargetDirEntry);
3134         }
3135
3136         //
3137         // Increment our ref count on the dir entry
3138         //
3139
3140         if( pTargetDirEntry != NULL)
3141         {
3142
3143             ASSERT( BooleanFlagOn( pTargetDirEntry->ObjectInformation->Flags, AFS_OBJECT_FLAGS_PARENT_FID) &&
3144                     AFSIsEqualFID( &pTargetParentObject->FileId, &pTargetDirEntry->ObjectInformation->ParentFileId));
3145
3146             lCount = InterlockedIncrement( &pTargetDirEntry->DirOpenReferenceCount);
3147
3148             AFSDbgTrace(( AFS_SUBSYSTEM_DIRENTRY_REF_COUNTING,
3149                           AFS_TRACE_LEVEL_VERBOSE,
3150                           "AFSSetRenameInfo Increment count on %wZ DE %p Ccb %p Cnt %d\n",
3151                           &pTargetDirEntry->NameInformation.FileName,
3152                           pTargetDirEntry,
3153                           pSrcCcb,
3154                           lCount));
3155
3156             ASSERT( lCount >= 0);
3157
3158             if( !bReplaceIfExists)
3159             {
3160
3161                 AFSDbgTrace(( AFS_SUBSYSTEM_FILE_PROCESSING,
3162                               AFS_TRACE_LEVEL_ERROR,
3163                               "AFSSetRenameInfo Attempt to rename directory with target collision %wZ Target %wZ\n",
3164                               &pSrcCcb->DirectoryCB->NameInformation.FileName,
3165                               &pTargetDirEntry->NameInformation.FileName));
3166
3167                 try_return( ntStatus = STATUS_OBJECT_NAME_COLLISION);
3168             }
3169
3170             AFSDbgTrace(( AFS_SUBSYSTEM_FILE_PROCESSING | AFS_SUBSYSTEM_DIRENTRY_REF_COUNTING,
3171                           AFS_TRACE_LEVEL_ERROR,
3172                           "AFSSetRenameInfo Target %wZ exists DE %p Count %d, performing delete of target\n",
3173                           &pTargetDirEntry->NameInformation.FileName,
3174                           pTargetDirEntry,
3175                           lCount));
3176
3177             //
3178             // Pull the directory entry from the parent
3179             //
3180
3181             AFSRemoveDirNodeFromParent( pTargetParentObject,
3182                                         pTargetDirEntry,
3183                                         FALSE);
3184
3185             bTargetEntryExists = TRUE;
3186         }
3187         else
3188         {
3189             AFSDbgTrace(( AFS_SUBSYSTEM_FILE_PROCESSING,
3190                           AFS_TRACE_LEVEL_VERBOSE,
3191                           "AFSSetRenameInfo Target does NOT exist, normal rename\n"));
3192         }
3193
3194         //
3195         // We need to remove the DirEntry from the parent node, update the index
3196         // and reinsert it into the parent tree. Note that for entries with the
3197         // same parent we do not pull the node from the enumeration list
3198         //
3199
3200         AFSRemoveDirNodeFromParent( pSrcParentObject,
3201                                     pSrcCcb->DirectoryCB,
3202                                     !bCommonParent);
3203
3204         //
3205         // OK, this is a simple rename. Issue the rename
3206         // request to the service.
3207         //
3208
3209         ntStatus = AFSNotifyRename( pSrcObject,
3210                                     &pSrcCcb->AuthGroup,
3211                                     pSrcParentObject,
3212                                     pTargetDcb->ObjectInformation,
3213                                     pSrcCcb->DirectoryCB,
3214                                     &uniTargetName,
3215                                     &stNewFid);
3216
3217         if( !NT_SUCCESS( ntStatus))
3218         {
3219
3220             //
3221             // Attempt to re-insert the directory entry
3222             //
3223
3224             AFSInsertDirectoryNode( pSrcParentObject,
3225                                     pSrcCcb->DirectoryCB,
3226                                     !bCommonParent);
3227
3228             AFSDbgTrace(( AFS_SUBSYSTEM_FILE_PROCESSING,
3229                           AFS_TRACE_LEVEL_ERROR,
3230                           "AFSSetRenameInfo Failed rename of %wZ to target %wZ Status %08lX\n",
3231                           &pSrcCcb->DirectoryCB->NameInformation.FileName,
3232                           &uniTargetName,
3233                           ntStatus));
3234
3235             try_return( ntStatus);
3236         }
3237
3238         //
3239         // Set the notification up for the source file
3240         //
3241
3242         if( pSrcParentObject == pTargetParentObject &&
3243             !bTargetEntryExists)
3244         {
3245
3246             ulNotificationAction = FILE_ACTION_RENAMED_OLD_NAME;
3247         }
3248         else
3249         {
3250
3251             ulNotificationAction = FILE_ACTION_REMOVED;
3252         }
3253
3254         if( pSrcObject->FileType == AFS_FILE_TYPE_DIRECTORY)
3255         {
3256
3257             ulNotifyFilter = FILE_NOTIFY_CHANGE_DIR_NAME;
3258         }
3259         else
3260         {
3261
3262             ulNotifyFilter = FILE_NOTIFY_CHANGE_FILE_NAME;
3263         }
3264
3265         AFSFsRtlNotifyFullReportChange( pSrcParentObject,
3266                                         pSrcCcb,
3267                                         (ULONG)ulNotifyFilter,
3268                                         (ULONG)ulNotificationAction);
3269
3270         //
3271         // Update the name in the dir entry.
3272         //
3273
3274         ntStatus = AFSUpdateDirEntryName( pSrcCcb->DirectoryCB,
3275                                           &uniTargetName);
3276
3277         if( !NT_SUCCESS( ntStatus))
3278         {
3279
3280             //
3281             // Attempt to re-insert the directory entry
3282             //
3283
3284             AFSInsertDirectoryNode( pSrcParentObject,
3285                                     pSrcCcb->DirectoryCB,
3286                                     !bCommonParent);
3287
3288             AFSDbgTrace(( AFS_SUBSYSTEM_FILE_PROCESSING,
3289                           AFS_TRACE_LEVEL_ERROR,
3290                           "AFSSetRenameInfo Failed update of dir entry %wZ to target %wZ Status %08lX\n",
3291                           &pSrcCcb->DirectoryCB->NameInformation.FileName,
3292                           &uniTargetName,
3293                           ntStatus));
3294
3295             try_return( ntStatus);
3296         }
3297
3298         //
3299         // Update the object information block, if needed
3300         //
3301
3302         if( !AFSIsEqualFID( &pSrcObject->FileId,
3303                             &stNewFid))
3304         {
3305
3306             AFSAcquireExcl( pSrcObject->VolumeCB->ObjectInfoTree.TreeLock,
3307                             TRUE);
3308
3309             //
3310             // Remove the old information entry
3311             //
3312
3313             AFSRemoveHashEntry( &pSrcObject->VolumeCB->ObjectInfoTree.TreeHead,
3314                                 &pSrcObject->TreeEntry);
3315
3316             RtlCopyMemory( &pSrcObject->FileId,
3317                            &stNewFid,
3318                            sizeof( AFSFileID));
3319
3320             //
3321             // Insert the entry into the new object table.
3322             //
3323
3324             pSrcObject->TreeEntry.HashIndex = AFSCreateLowIndex( &pSrcObject->FileId);
3325
3326             if( pSrcObject->VolumeCB->ObjectInfoTree.TreeHead == NULL)
3327             {
3328
3329                 pSrcObject->VolumeCB->ObjectInfoTree.TreeHead = &pSrcObject->TreeEntry;
3330             }
3331             else
3332             {
3333
3334                 if ( !NT_SUCCESS( AFSInsertHashEntry( pSrcObject->VolumeCB->ObjectInfoTree.TreeHead,
3335                                                      &pSrcObject->TreeEntry)))
3336                 {
3337
3338                     //
3339                     // Lost a race, an ObjectInfo object already exists for this FID.
3340                     // Let this copy be garbage collected.
3341                     //
3342
3343                     ClearFlag( pSrcObject->Flags, AFS_OBJECT_INSERTED_HASH_TREE);
3344                 }
3345             }
3346
3347             AFSReleaseResource( pSrcObject->VolumeCB->ObjectInfoTree.TreeLock);
3348         }
3349
3350         //
3351         // Update the hash values for the name trees.
3352         //
3353
3354         pSrcCcb->DirectoryCB->CaseSensitiveTreeEntry.HashIndex = AFSGenerateCRC( &pSrcCcb->DirectoryCB->NameInformation.FileName,
3355                                                                                  FALSE);
3356
3357         pSrcCcb->DirectoryCB->CaseInsensitiveTreeEntry.HashIndex = AFSGenerateCRC( &pSrcCcb->DirectoryCB->NameInformation.FileName,
3358                                                                                    TRUE);
3359
3360         if( !BooleanFlagOn( pDeviceExt->DeviceFlags, AFS_DEVICE_FLAG_DISABLE_SHORTNAMES) &&
3361             pSrcCcb->DirectoryCB->NameInformation.ShortNameLength > 0 &&
3362             !RtlIsNameLegalDOS8Dot3( &pSrcCcb->DirectoryCB->NameInformation.FileName,
3363                                      NULL,
3364                                      NULL))
3365         {
3366
3367             uniShortName.Length = pSrcCcb->DirectoryCB->NameInformation.ShortNameLength;
3368             uniShortName.MaximumLength = uniShortName.Length;
3369             uniShortName.Buffer = pSrcCcb->DirectoryCB->NameInformation.ShortName;
3370
3371             pSrcCcb->DirectoryCB->Type.Data.ShortNameTreeEntry.HashIndex = AFSGenerateCRC( &uniShortName,
3372                                                                                            TRUE);
3373
3374             AFSDbgTrace(( AFS_SUBSYSTEM_FILE_PROCESSING,
3375                           AFS_TRACE_LEVEL_VERBOSE,
3376                           "AFSSetRenameInfo Initialized short name hash for %wZ longname %wZ\n",
3377                           &uniShortName,
3378                           &pSrcCcb->DirectoryCB->NameInformation.FileName));
3379         }
3380         else
3381         {
3382
3383             pSrcCcb->DirectoryCB->Type.Data.ShortNameTreeEntry.HashIndex = 0;
3384         }
3385
3386         if( !bCommonParent)
3387         {
3388
3389             //
3390             // Update the file index for the object in the new parent
3391             //
3392
3393             pSrcCcb->DirectoryCB->FileIndex = (ULONG)InterlockedIncrement( &pTargetParentObject->Specific.Directory.DirectoryNodeHdr.ContentIndex);
3394         }
3395
3396         //
3397         // Re-insert the directory entry
3398         //
3399
3400         AFSInsertDirectoryNode( pTargetParentObject,
3401                                 pSrcCcb->DirectoryCB,
3402                                 !bCommonParent);
3403
3404         //
3405         // Update the parent pointer in the source object if they are different
3406         //
3407
3408         if( pSrcParentObject != pTargetParentObject)
3409         {
3410
3411             lCount = InterlockedDecrement( &pSrcParentObject->Specific.Directory.ChildOpenHandleCount);
3412
3413             lCount = InterlockedDecrement( &pSrcParentObject->Specific.Directory.ChildOpenReferenceCount);
3414
3415             lCount = InterlockedIncrement( &pTargetParentObject->Specific.Directory.ChildOpenHandleCount);
3416
3417             lCount = InterlockedIncrement( &pTargetParentObject->Specific.Directory.ChildOpenReferenceCount);
3418
3419
3420             //
3421             // Guaranteed to be in the same volume
3422             //
3423
3424             AFSAcquireExcl( pSrcParentObject->VolumeCB->ObjectInfoTree.TreeLock,
3425                             TRUE);
3426
3427             lCount = AFSObjectInfoIncrement( pTargetParentObject,
3428                                              AFS_OBJECT_REFERENCE_CHILD);
3429
3430             AFSDbgTrace(( AFS_SUBSYSTEM_OBJECT_REF_COUNTING,
3431                           AFS_TRACE_LEVEL_VERBOSE,
3432                           "AFSSetRenameInfo Increment count on parent object %p Cnt %d\n",
3433                           pTargetParentObject,
3434                           lCount));
3435
3436             lCount = AFSObjectInfoDecrement( pSrcParentObject,
3437                                              AFS_OBJECT_REFERENCE_CHILD);
3438
3439             AFSDbgTrace(( AFS_SUBSYSTEM_OBJECT_REF_COUNTING,
3440                           AFS_TRACE_LEVEL_VERBOSE,
3441                           "AFSSetRenameInfo Decrement count on parent object %p Cnt %d\n",
3442                           pSrcParentObject,
3443                           lCount));
3444
3445             pSrcObject->ParentFileId = pTargetParentObject->FileId;
3446
3447             SetFlag( pSrcObject->Flags, AFS_OBJECT_FLAGS_PARENT_FID);
3448
3449             AFSReleaseResource( pSrcParentObject->VolumeCB->ObjectInfoTree.TreeLock);
3450
3451             ulNotificationAction = FILE_ACTION_ADDED;
3452         }
3453         else
3454         {
3455
3456             ulNotificationAction = FILE_ACTION_RENAMED_NEW_NAME;
3457         }
3458
3459         //
3460         // Now update the notification for the target file
3461         //
3462
3463         AFSFsRtlNotifyFullReportChange( pTargetParentObject,
3464                                         pSrcCcb,
3465                                         (ULONG)ulNotifyFilter,
3466                                         (ULONG)ulNotificationAction);
3467
3468         //
3469         // If we performed the rename of the target because it existed, we now need to
3470         // delete the tmp target we created above
3471         //
3472
3473         if( bTargetEntryExists)
3474         {
3475
3476             AFSDbgTrace(( AFS_SUBSYSTEM_FILE_PROCESSING,
3477                           AFS_TRACE_LEVEL_VERBOSE,
3478                           "AFSSetRenameInfo Setting DELETE flag in dir entry %p name %wZ\n",
3479                           pTargetDirEntry,
3480                           &pTargetDirEntry->NameInformation.FileName));
3481
3482             SetFlag( pTargetDirEntry->Flags, AFS_DIR_ENTRY_DELETED);
3483
3484             //
3485             // Try and purge the cache map if this is a file
3486             //
3487
3488             if( pTargetDirEntry->ObjectInformation->FileType == AFS_FILE_TYPE_FILE &&
3489                 pTargetDirEntry->ObjectInformation->Fcb != NULL &&
3490                 pTargetDirEntry->DirOpenReferenceCount > 1)
3491             {
3492
3493                 pTargetFcb = pTargetDirEntry->ObjectInformation->Fcb;
3494             }
3495
3496             ASSERT( pTargetDirEntry->DirOpenReferenceCount > 0);
3497
3498             lCount = InterlockedDecrement( &pTargetDirEntry->DirOpenReferenceCount); // The count we added above
3499
3500             AFSDbgTrace(( AFS_SUBSYSTEM_DIRENTRY_REF_COUNTING,
3501                           AFS_TRACE_LEVEL_VERBOSE,
3502                           "AFSSetRenameInfo Decrement count on %wZ DE %p Ccb %p Cnt %d\n",
3503                           &pTargetDirEntry->NameInformation.FileName,
3504                           pTargetDirEntry,
3505                           pSrcCcb,
3506                           lCount));
3507
3508             ASSERT( lCount >= 0);
3509
3510             if( lCount == 0 &&
3511                 pTargetDirEntry->NameArrayReferenceCount <= 0)
3512             {
3513
3514                 AFSDbgTrace(( AFS_SUBSYSTEM_FILE_PROCESSING,
3515                               AFS_TRACE_LEVEL_VERBOSE,
3516                               "AFSSetRenameInfo Deleting dir entry %p name %wZ\n",
3517                               pTargetDirEntry,
3518                               &pTargetDirEntry->NameInformation.FileName));
3519
3520                 AFSDeleteDirEntry( pTargetParentObject,
3521                                    &pTargetDirEntry);
3522             }
3523
3524             pTargetDirEntry = NULL;
3525
3526             if ( pTargetFcb != NULL)
3527             {
3528
3529                 //
3530                 // Do not hold TreeLocks across the MmForceSectionClosed() call as
3531                 // it can deadlock with Trend Micro's TmPreFlt!TmpQueryFullName
3532                 //
3533
3534                 if( bReleaseTargetDirLock)
3535                 {
3536                     AFSReleaseResource( pTargetParentObject->Specific.Directory.DirectoryNodeHdr.TreeLock);
3537
3538                     bReleaseTargetDirLock = FALSE;
3539                 }
3540
3541                 if( bReleaseSourceDirLock)
3542                 {
3543
3544                     AFSReleaseResource( pSourceDirLock);
3545
3546                     bReleaseSourceDirLock = FALSE;
3547                 }
3548
3549                 //
3550                 // MmForceSectionClosed() can eventually call back into AFSCleanup
3551                 // which will need to acquire Fcb->Resource exclusively.  Failure
3552                 // to obtain it here before holding the SectionObjectResource will
3553                 // permit the locks to be obtained out of order risking a deadlock.
3554                 //
3555
3556                 AFSDbgTrace(( AFS_SUBSYSTEM_LOCK_PROCESSING|AFS_SUBSYSTEM_SECTION_OBJECT,
3557                               AFS_TRACE_LEVEL_VERBOSE,
3558                               "AFSSetRenameInfo Acquiring Fcb lock %p EXCL %08lX\n",
3559                               &pTargetFcb->NPFcb->Resource,
3560                               PsGetCurrentThread()));
3561
3562                 AFSAcquireExcl( &pTargetFcb->NPFcb->Resource,
3563                                 TRUE);
3564
3565                 AFSDbgTrace(( AFS_SUBSYSTEM_LOCK_PROCESSING|AFS_SUBSYSTEM_SECTION_OBJECT,
3566                               AFS_TRACE_LEVEL_VERBOSE,
3567                               "AFSSetRenameInfo Acquiring Fcb SectionObject lock %p EXCL %08lX\n",
3568                               &pTargetFcb->NPFcb->SectionObjectResource,
3569                               PsGetCurrentThread()));
3570
3571                 AFSAcquireExcl( &pTargetFcb->NPFcb->SectionObjectResource,
3572                                 TRUE);
3573
3574                 __try
3575                 {
3576
3577                     //
3578                     // Close the section in the event it was mapped
3579                     //
3580
3581                     if( !MmForceSectionClosed( &pTargetFcb->NPFcb->SectionObjectPointers,
3582                                                TRUE))
3583                     {
3584
3585                         AFSDbgTrace(( AFS_SUBSYSTEM_FILE_PROCESSING,
3586                                       AFS_TRACE_LEVEL_ERROR,
3587                                       "AFSSetRenameInfo Failed to delete section for target file %wZ\n",
3588                                       &uniTargetName));
3589                     }
3590                 }
3591                 __except( AFSExceptionFilter( __FUNCTION__, GetExceptionCode(), GetExceptionInformation()))
3592                 {
3593
3594                     ntStatus = GetExceptionCode();
3595
3596                     AFSDbgTrace(( 0,
3597                                   0,
3598                                   "EXCEPTION - AFSSetRenameInfo MmForceSectionClosed failed FID %08lX-%08lX-%08lX-%08lX Status 0x%08lX\n",
3599                                   pTargetFcb->ObjectInformation->FileId.Cell,
3600                                   pTargetFcb->ObjectInformation->FileId.Volume,
3601                                   pTargetFcb->ObjectInformation->FileId.Vnode,
3602                                   pTargetFcb->ObjectInformation->FileId.Unique,
3603                                   ntStatus));
3604                 }
3605
3606                 AFSDbgTrace(( AFS_SUBSYSTEM_LOCK_PROCESSING|AFS_SUBSYSTEM_SECTION_OBJECT,
3607                               AFS_TRACE_LEVEL_VERBOSE,
3608                               "AFSSetRenameInfo Releasing Fcb SectionObject lock %p EXCL %08lX\n",
3609                               &pTargetFcb->NPFcb->SectionObjectResource,
3610                               PsGetCurrentThread()));
3611
3612                 AFSReleaseResource( &pTargetFcb->NPFcb->SectionObjectResource);
3613
3614                 AFSDbgTrace(( AFS_SUBSYSTEM_LOCK_PROCESSING,
3615                               AFS_TRACE_LEVEL_VERBOSE,
3616                               "AFSSetRenameInfo Releasing Fcb lock %p EXCL %08lX\n",
3617                               &pTargetFcb->NPFcb->Resource,
3618                               PsGetCurrentThread()));
3619
3620                 AFSReleaseResource( &pTargetFcb->NPFcb->Resource);
3621             }
3622         }
3623
3624 try_exit:
3625
3626         if( !NT_SUCCESS( ntStatus))
3627         {
3628
3629             if( bTargetEntryExists)
3630             {
3631
3632                 ASSERT( pTargetParentObject != NULL);
3633
3634                 AFSInsertDirectoryNode( pTargetParentObject,
3635                                         pTargetDirEntry,
3636                                         FALSE);
3637             }
3638         }
3639
3640         if( pTargetDirEntry != NULL)
3641         {
3642
3643             lCount = InterlockedDecrement( &pTargetDirEntry->DirOpenReferenceCount);
3644
3645             AFSDbgTrace(( AFS_SUBSYSTEM_DIRENTRY_REF_COUNTING,
3646                           AFS_TRACE_LEVEL_VERBOSE,
3647                           "AFSSetRenameInfo Decrement2 count on %wZ DE %p Ccb %p Cnt %d\n",
3648                           &pTargetDirEntry->NameInformation.FileName,
3649                           pTargetDirEntry,
3650                           pSrcCcb,
3651                           lCount));
3652
3653             ASSERT( lCount >= 0);
3654         }
3655
3656         if( bReleaseTargetDirLock)
3657         {
3658
3659             AFSReleaseResource( pTargetParentObject->Specific.Directory.DirectoryNodeHdr.TreeLock);
3660         }
3661
3662         if( bReleaseSourceDirLock)
3663         {
3664
3665             AFSReleaseResource( pSourceDirLock);
3666         }
3667
3668         if ( bDereferenceTargetParentObject)
3669         {
3670
3671             ObDereferenceObject( pTargetParentFileObj);
3672         }
3673
3674         if ( pSrcParentObject != NULL)
3675         {
3676
3677             AFSReleaseObjectInfo( &pSrcParentObject);
3678         }
3679
3680         //
3681         // No need to release pTargetParentObject as it is either a copy of pSrcParentObject
3682         // or (AFSFcb *)pTargetFileObj->FsContext->ObjectInformation
3683         //
3684
3685         pTargetParentObject = NULL;
3686     }
3687
3688     return ntStatus;
3689 }
3690
3691 NTSTATUS
3692 AFSSetPositionInfo( IN PIRP Irp,
3693                     IN AFSDirectoryCB *DirectoryCB)
3694 {
3695     UNREFERENCED_PARAMETER(DirectoryCB);
3696     NTSTATUS ntStatus = STATUS_SUCCESS;
3697     PFILE_POSITION_INFORMATION pBuffer;
3698     PIO_STACK_LOCATION pIrpSp = IoGetCurrentIrpStackLocation( Irp);
3699
3700     pBuffer = (PFILE_POSITION_INFORMATION)Irp->AssociatedIrp.SystemBuffer;
3701
3702     pIrpSp->FileObject->CurrentByteOffset.QuadPart = pBuffer->CurrentByteOffset.QuadPart;
3703
3704     return ntStatus;
3705 }
3706
3707 NTSTATUS
3708 AFSSetAllocationInfo( IN PIRP Irp,
3709                       IN AFSDirectoryCB *DirectoryCB)
3710 {
3711     UNREFERENCED_PARAMETER(DirectoryCB);
3712     NTSTATUS ntStatus = STATUS_SUCCESS;
3713     PFILE_ALLOCATION_INFORMATION pBuffer;
3714     BOOLEAN bReleasePaging = FALSE;
3715     BOOLEAN bTellCc = FALSE;
3716     BOOLEAN bTellService = FALSE;
3717     BOOLEAN bUserMapped = FALSE;
3718     PIO_STACK_LOCATION pIrpSp = IoGetCurrentIrpStackLocation( Irp);
3719     PFILE_OBJECT pFileObject = pIrpSp->FileObject;
3720     AFSFcb *pFcb = NULL;
3721     AFSCcb *pCcb = NULL;
3722     LARGE_INTEGER liSaveAlloc;
3723     LARGE_INTEGER liSaveFileSize;
3724     LARGE_INTEGER liSaveVDL;
3725
3726     pBuffer = (PFILE_ALLOCATION_INFORMATION)Irp->AssociatedIrp.SystemBuffer;
3727
3728     pFcb = (AFSFcb *)pIrpSp->FileObject->FsContext;
3729
3730     pCcb = (AFSCcb *)pIrpSp->FileObject->FsContext2;
3731
3732     //
3733     // save values to put back
3734     //
3735     liSaveAlloc = pFcb->Header.AllocationSize;
3736     liSaveFileSize = pFcb->Header.FileSize;
3737     liSaveVDL = pFcb->Header.ValidDataLength;
3738
3739     if( pFcb->Header.AllocationSize.QuadPart == pBuffer->AllocationSize.QuadPart ||
3740         pIrpSp->Parameters.SetFile.AdvanceOnly)
3741     {
3742         return STATUS_SUCCESS ;
3743     }
3744
3745     if( pFcb->Header.AllocationSize.QuadPart > pBuffer->AllocationSize.QuadPart)
3746     {
3747
3748         AFSDbgTrace(( AFS_SUBSYSTEM_LOCK_PROCESSING|AFS_SUBSYSTEM_SECTION_OBJECT,
3749                       AFS_TRACE_LEVEL_VERBOSE,
3750                       "AFSSetAllocationInfo Acquiring Fcb SectionObject lock %p EXCL %08lX\n",
3751                       &pFcb->NPFcb->SectionObjectResource,
3752                       PsGetCurrentThread()));
3753
3754         AFSAcquireExcl( &pFcb->NPFcb->SectionObjectResource,
3755                         TRUE);
3756
3757         __try
3758         {
3759
3760             bUserMapped = !MmCanFileBeTruncated( pFileObject->SectionObjectPointer,
3761                                                  &pBuffer->AllocationSize);
3762         }
3763         __except( AFSExceptionFilter( __FUNCTION__, GetExceptionCode(), GetExceptionInformation()))
3764         {
3765
3766             bUserMapped = FALSE;
3767
3768             ntStatus = GetExceptionCode();
3769
3770             AFSDbgTrace(( 0,
3771                           0,
3772                           "EXCEPTION - AFSSetAllocationInfo MmCanFileBeTruncated failed FID %08lX-%08lX-%08lX-%08lX Status 0x%08lX\n",
3773                           pFcb->ObjectInformation->FileId.Cell,
3774                           pFcb->ObjectInformation->FileId.Volume,
3775                           pFcb->ObjectInformation->FileId.Vnode,
3776                           pFcb->ObjectInformation->FileId.Unique,
3777                           ntStatus));
3778         }
3779
3780         AFSDbgTrace(( AFS_SUBSYSTEM_LOCK_PROCESSING|AFS_SUBSYSTEM_SECTION_OBJECT,
3781                       AFS_TRACE_LEVEL_VERBOSE,
3782                       "AFSSetAllocationInfo Releasing Fcb SectionObject lock %p EXCL %08lX\n",
3783                       &pFcb->NPFcb->SectionObjectResource,
3784                       PsGetCurrentThread()));
3785
3786         AFSReleaseResource( &pFcb->NPFcb->SectionObjectResource);
3787
3788         //
3789         // Truncating the file
3790         //
3791         if ( bUserMapped)
3792         {
3793
3794             ntStatus = STATUS_USER_MAPPED_FILE ;
3795         }
3796         else
3797         {
3798
3799             //
3800             // If this is a truncation we need to grab the paging IO resource.
3801             //
3802
3803             AFSDbgTrace(( AFS_SUBSYSTEM_LOCK_PROCESSING,
3804                           AFS_TRACE_LEVEL_VERBOSE,
3805                           "AFSSetAllocationInfo Acquiring Fcb PagingIo lock %p EXCL %08lX\n",
3806                           &pFcb->NPFcb->PagingResource,
3807                           PsGetCurrentThread()));
3808
3809             AFSAcquireExcl( &pFcb->NPFcb->PagingResource,
3810                             TRUE);
3811
3812             bReleasePaging = TRUE;
3813
3814             //
3815             // Must drop the Fcb Resource.  When changing the file size
3816             // a deadlock can occur with Trend Micro's filter if the file
3817             // size is set to zero.
3818             //
3819
3820             AFSReleaseResource( &pFcb->NPFcb->Resource);
3821
3822             pFcb->Header.AllocationSize = pBuffer->AllocationSize;
3823
3824             pFcb->ObjectInformation->AllocationSize = pBuffer->AllocationSize;
3825
3826             //
3827             // Tell Cc that Allocation is moved.
3828             //
3829             bTellCc = TRUE;
3830
3831             if( pFcb->Header.FileSize.QuadPart > pBuffer->AllocationSize.QuadPart)
3832             {
3833                 //
3834                 // We are pulling the EOF back as well so we need to tell
3835                 // the service.
3836                 //
3837                 bTellService = TRUE;
3838
3839                 pFcb->Header.FileSize = pBuffer->AllocationSize;
3840
3841                 pFcb->ObjectInformation->EndOfFile = pBuffer->AllocationSize;
3842             }
3843
3844         }
3845     }
3846     else
3847     {
3848         //
3849         // Tell Cc if allocation is increased.
3850         //
3851
3852         AFSDbgTrace(( AFS_SUBSYSTEM_LOCK_PROCESSING,
3853                       AFS_TRACE_LEVEL_VERBOSE,
3854                       "AFSSetAllocationInfo Acquiring Fcb PagingIo lock %p EXCL %08lX\n",
3855                       &pFcb->NPFcb->PagingResource,
3856                       PsGetCurrentThread()));
3857
3858         AFSAcquireExcl( &pFcb->NPFcb->PagingResource,
3859                         TRUE);
3860
3861         bReleasePaging = TRUE;
3862
3863         //
3864         // Must drop the Fcb Resource.  When changing the file size
3865         // a deadlock can occur with Trend Micro's filter if the file
3866         // size is set to zero.
3867         //
3868
3869         AFSReleaseResource( &pFcb->NPFcb->Resource);
3870
3871         bTellCc = pBuffer->AllocationSize.QuadPart > pFcb->Header.AllocationSize.QuadPart;
3872
3873         pFcb->Header.AllocationSize = pBuffer->AllocationSize;
3874
3875         pFcb->ObjectInformation->AllocationSize = pBuffer->AllocationSize;
3876     }
3877
3878     //
3879     // Now Tell the server if we have to
3880     //
3881     if (bTellService)
3882     {
3883
3884         ASSERT( BooleanFlagOn( pFcb->ObjectInformation->Flags, AFS_OBJECT_FLAGS_PARENT_FID));
3885
3886         ntStatus = AFSUpdateFileInformation( &pFcb->ObjectInformation->ParentFileId,
3887                                              pFcb->ObjectInformation,
3888                                              &pCcb->AuthGroup);
3889     }
3890
3891     if (NT_SUCCESS(ntStatus))
3892     {
3893         //
3894         // Trim extents if we told the service - the update has done an implicit
3895         // trim at the service.
3896         //
3897         if (bTellService)
3898         {
3899             AFSTrimExtents( pFcb,
3900                             &pFcb->Header.FileSize);
3901         }
3902
3903         KeQuerySystemTime( &pFcb->ObjectInformation->ChangeTime);
3904
3905         SetFlag( pFcb->Flags, AFS_FCB_FLAG_FILE_MODIFIED | AFS_FCB_FLAG_UPDATE_CHANGE_TIME);
3906
3907         if (bTellCc &&
3908             CcIsFileCached( pFileObject))
3909         {
3910             CcSetFileSizes( pFileObject,
3911                             (PCC_FILE_SIZES)&pFcb->Header.AllocationSize);
3912         }
3913
3914         //
3915         // Mark the file as modified so as to reflect the change into the last write on close.
3916         //
3917         SetFlag( pFileObject->Flags, FO_FILE_MODIFIED);
3918     }
3919     else
3920     {
3921         //
3922         // Put the saved values back
3923         //
3924         pFcb->Header.ValidDataLength = liSaveVDL;
3925         pFcb->Header.FileSize = liSaveFileSize;
3926         pFcb->Header.AllocationSize = liSaveAlloc;
3927         pFcb->ObjectInformation->EndOfFile = liSaveFileSize;
3928         pFcb->ObjectInformation->AllocationSize = liSaveAlloc;
3929     }
3930
3931     if( bReleasePaging)
3932     {
3933
3934         AFSReleaseResource( &pFcb->NPFcb->PagingResource);
3935
3936         AFSAcquireExcl( &pFcb->NPFcb->Resource,
3937                         TRUE);
3938     }
3939
3940     return ntStatus;
3941 }
3942
3943 NTSTATUS
3944 AFSSetEndOfFileInfo( IN PIRP Irp,
3945                      IN AFSDirectoryCB *DirectoryCB)
3946 {
3947     UNREFERENCED_PARAMETER(DirectoryCB);
3948     NTSTATUS ntStatus = STATUS_SUCCESS;
3949     PFILE_END_OF_FILE_INFORMATION pBuffer;
3950     PIO_STACK_LOCATION pIrpSp = IoGetCurrentIrpStackLocation( Irp);
3951     PFILE_OBJECT pFileObject = pIrpSp->FileObject;
3952     LARGE_INTEGER liSaveSize;
3953     LARGE_INTEGER liSaveVDL;
3954     LARGE_INTEGER liSaveAlloc;
3955     BOOLEAN bModified = FALSE;
3956     BOOLEAN bReleasePaging = FALSE;
3957     BOOLEAN bTruncated = FALSE;
3958     BOOLEAN bUserMapped = FALSE;
3959     AFSFcb *pFcb = NULL;
3960     AFSCcb *pCcb = NULL;
3961
3962     pFcb = (AFSFcb *)pIrpSp->FileObject->FsContext;
3963
3964     pCcb = (AFSCcb *)pIrpSp->FileObject->FsContext2;
3965
3966     pBuffer = (PFILE_END_OF_FILE_INFORMATION)Irp->AssociatedIrp.SystemBuffer;
3967
3968     liSaveSize = pFcb->Header.FileSize;
3969     liSaveAlloc = pFcb->Header.AllocationSize;
3970     liSaveVDL = pFcb->Header.ValidDataLength;
3971
3972     if( pFcb->Header.FileSize.QuadPart != pBuffer->EndOfFile.QuadPart &&
3973         !pIrpSp->Parameters.SetFile.AdvanceOnly)
3974     {
3975
3976         if( pBuffer->EndOfFile.QuadPart < pFcb->Header.FileSize.QuadPart)
3977         {
3978
3979             AFSDbgTrace(( AFS_SUBSYSTEM_LOCK_PROCESSING|AFS_SUBSYSTEM_SECTION_OBJECT,
3980                           AFS_TRACE_LEVEL_VERBOSE,
3981                           "AFSSetEndOfFileInfo Acquiring Fcb SectionObject lock %p EXCL %08lX\n",
3982                           &pFcb->NPFcb->SectionObjectResource,
3983                           PsGetCurrentThread()));
3984
3985             AFSAcquireExcl( &pFcb->NPFcb->SectionObjectResource,
3986                             TRUE);
3987
3988             __try
3989             {
3990
3991                 bUserMapped = !MmCanFileBeTruncated( pFileObject->SectionObjectPointer,
3992                                                      &pBuffer->EndOfFile);
3993             }
3994             __except( AFSExceptionFilter( __FUNCTION__, GetExceptionCode(), GetExceptionInformation()))
3995             {
3996
3997                 bUserMapped = FALSE;
3998
3999                 ntStatus = GetExceptionCode();
4000
4001                 AFSDbgTrace(( 0,
4002                               0,
4003                               "EXCEPTION - AFSSetEndOfFileInfo MmCanFileBeTruncated failed FID %08lX-%08lX-%08lX-%08lX Status 0x%08lX\n",
4004                               pFcb->ObjectInformation->FileId.Cell,
4005                               pFcb->ObjectInformation->FileId.Volume,
4006                               pFcb->ObjectInformation->FileId.Vnode,
4007                               pFcb->ObjectInformation->FileId.Unique,
4008                               ntStatus));
4009             }
4010
4011             AFSDbgTrace(( AFS_SUBSYSTEM_LOCK_PROCESSING|AFS_SUBSYSTEM_SECTION_OBJECT,
4012                           AFS_TRACE_LEVEL_VERBOSE,
4013                           "AFSSetEndOfFileInfo Releasing Fcb SectionObject lock %p EXCL %08lX\n",
4014                           &pFcb->NPFcb->SectionObjectResource,
4015                           PsGetCurrentThread()));
4016
4017             AFSReleaseResource( &pFcb->NPFcb->SectionObjectResource);
4018
4019             // Truncating the file
4020             if ( bUserMapped)
4021             {
4022
4023                 ntStatus = STATUS_USER_MAPPED_FILE;
4024             }
4025             else
4026             {
4027
4028                 //
4029                 // If this is a truncation we need to grab the paging
4030                 // IO resource.
4031                 //
4032                 AFSDbgTrace(( AFS_SUBSYSTEM_LOCK_PROCESSING,
4033                               AFS_TRACE_LEVEL_VERBOSE,
4034                               "AFSSetEndOfFileInfo Acquiring Fcb PagingIo lock %p EXCL %08lX\n",
4035                               &pFcb->NPFcb->PagingResource,
4036                               PsGetCurrentThread()));
4037
4038                 AFSAcquireExcl( &pFcb->NPFcb->PagingResource,
4039                                 TRUE);
4040
4041                 bReleasePaging = TRUE;
4042
4043                 //
4044                 // Must drop the Fcb Resource.  When changing the file size
4045                 // a deadlock can occur with Trend Micro's filter if the file
4046                 // size is set to zero.
4047                 //
4048
4049                 AFSReleaseResource( &pFcb->NPFcb->Resource);
4050
4051                 pFcb->Header.AllocationSize = pBuffer->EndOfFile;
4052
4053                 pFcb->Header.FileSize = pBuffer->EndOfFile;
4054
4055                 pFcb->ObjectInformation->EndOfFile = pBuffer->EndOfFile;
4056
4057                 pFcb->ObjectInformation->AllocationSize = pBuffer->EndOfFile;
4058
4059                 if( pFcb->Header.ValidDataLength.QuadPart > pFcb->Header.FileSize.QuadPart)
4060                 {
4061
4062                     pFcb->Header.ValidDataLength = pFcb->Header.FileSize;
4063                 }
4064
4065                 bTruncated = TRUE;
4066
4067                 bModified = TRUE;
4068             }
4069         }
4070         else
4071         {
4072
4073             //
4074             // extending the file, move EOF
4075             //
4076
4077             //
4078             // If this is a truncation we need to grab the paging
4079             // IO resource.
4080             //
4081             AFSDbgTrace(( AFS_SUBSYSTEM_LOCK_PROCESSING,
4082                           AFS_TRACE_LEVEL_VERBOSE,
4083                           "AFSSetEndOfFileInfo Acquiring Fcb PagingIo lock %p EXCL %08lX\n",
4084                           &pFcb->NPFcb->PagingResource,
4085                           PsGetCurrentThread()));
4086
4087             AFSAcquireExcl( &pFcb->NPFcb->PagingResource,
4088                             TRUE);
4089
4090             bReleasePaging = TRUE;
4091
4092             //
4093             // Must drop the Fcb Resource.  When changing the file size
4094             // a deadlock can occur with Trend Micro's filter if the file
4095             // size is set to zero.
4096             //
4097
4098             AFSReleaseResource( &pFcb->NPFcb->Resource);
4099
4100             pFcb->Header.FileSize = pBuffer->EndOfFile;
4101
4102             pFcb->ObjectInformation->EndOfFile = pBuffer->EndOfFile;
4103
4104             if (pFcb->Header.FileSize.QuadPart > pFcb->Header.AllocationSize.QuadPart)
4105             {
4106                 //
4107                 // And Allocation as needed.
4108                 //
4109                 pFcb->Header.AllocationSize = pBuffer->EndOfFile;
4110
4111                 pFcb->ObjectInformation->AllocationSize = pBuffer->EndOfFile;
4112             }
4113
4114             bModified = TRUE;
4115         }
4116     }
4117
4118     if (bModified)
4119     {
4120
4121         KeQuerySystemTime( &pFcb->ObjectInformation->ChangeTime);
4122
4123         SetFlag( pFcb->Flags, AFS_FCB_FLAG_FILE_MODIFIED | AFS_FCB_FLAG_UPDATE_CHANGE_TIME);
4124
4125         //
4126         // Tell the server
4127         //
4128
4129         ASSERT( BooleanFlagOn( pFcb->ObjectInformation->Flags, AFS_OBJECT_FLAGS_PARENT_FID));
4130
4131         ntStatus = AFSUpdateFileInformation( &pFcb->ObjectInformation->ParentFileId,
4132                                              pFcb->ObjectInformation,
4133                                              &pCcb->AuthGroup);
4134
4135         if( NT_SUCCESS(ntStatus))
4136         {
4137             //
4138             // We are now good to go so tell CC.
4139             //
4140             CcSetFileSizes( pFileObject,
4141                             (PCC_FILE_SIZES)&pFcb->Header.AllocationSize);
4142
4143             //
4144             // And give up those extents
4145             //
4146             if( bTruncated)
4147             {
4148
4149                 AFSTrimExtents( pFcb,
4150                                 &pFcb->Header.FileSize);
4151             }
4152
4153             //
4154             // Mark the file as modified so as to reflect the change into the last write on close.
4155             //
4156             SetFlag( pFileObject->Flags, FO_FILE_MODIFIED);
4157         }
4158         else
4159         {
4160             pFcb->Header.ValidDataLength = liSaveVDL;
4161             pFcb->Header.FileSize = liSaveSize;
4162             pFcb->Header.AllocationSize = liSaveAlloc;
4163             pFcb->ObjectInformation->EndOfFile = liSaveSize;
4164             pFcb->ObjectInformation->AllocationSize = liSaveAlloc;
4165         }
4166     }
4167
4168     if( bReleasePaging)
4169     {
4170
4171         AFSReleaseResource( &pFcb->NPFcb->PagingResource);
4172
4173         AFSAcquireExcl( &pFcb->NPFcb->Resource,
4174                         TRUE);
4175     }
4176
4177     return ntStatus;
4178 }
4179
4180 NTSTATUS
4181 AFSProcessShareSetInfo( IN IRP *Irp,
4182                         IN AFSFcb *Fcb,
4183                         IN AFSCcb *Ccb)
4184 {
4185
4186     UNREFERENCED_PARAMETER(Fcb);
4187     NTSTATUS ntStatus = STATUS_SUCCESS;
4188     PIO_STACK_LOCATION pIrpSp = IoGetCurrentIrpStackLocation( Irp);
4189     FILE_INFORMATION_CLASS ulFileInformationClass;
4190     void *pPipeInfo = NULL;
4191
4192     __Enter
4193     {
4194         ulFileInformationClass = pIrpSp->Parameters.SetFile.FileInformationClass;
4195
4196         AFSDbgTrace(( AFS_SUBSYSTEM_PIPE_PROCESSING,
4197                       AFS_TRACE_LEVEL_VERBOSE,
4198                       "AFSProcessShareSetInfo On pipe %wZ Class %08lX\n",
4199                       &Ccb->DirectoryCB->NameInformation.FileName,
4200                       ulFileInformationClass));
4201
4202         pPipeInfo = AFSLockSystemBuffer( Irp,
4203                                          pIrpSp->Parameters.SetFile.Length);
4204
4205         if( pPipeInfo == NULL)
4206         {
4207
4208             AFSDbgTrace(( AFS_SUBSYSTEM_PIPE_PROCESSING,
4209                           AFS_TRACE_LEVEL_ERROR,
4210                           "AFSProcessShareSetInfo Failed to lock buffer on pipe %wZ\n",
4211                           &Ccb->DirectoryCB->NameInformation.FileName));
4212
4213             try_return( ntStatus = STATUS_INSUFFICIENT_RESOURCES);
4214         }
4215
4216         //
4217         // Send the request to the service
4218         //
4219
4220         ntStatus = AFSNotifySetPipeInfo( Ccb,
4221                                          (ULONG)ulFileInformationClass,
4222                                          pIrpSp->Parameters.SetFile.Length,
4223                                          pPipeInfo);
4224
4225         if( !NT_SUCCESS( ntStatus))
4226         {
4227
4228             AFSDbgTrace(( AFS_SUBSYSTEM_PIPE_PROCESSING,
4229                           AFS_TRACE_LEVEL_ERROR,
4230                           "AFSProcessShareSetInfo Failed to send request to service on pipe %wZ Status %08lX\n",
4231                           &Ccb->DirectoryCB->NameInformation.FileName,
4232                           ntStatus));
4233
4234             try_return( ntStatus);
4235         }
4236
4237         AFSDbgTrace(( AFS_SUBSYSTEM_PIPE_PROCESSING,
4238                       AFS_TRACE_LEVEL_VERBOSE,
4239                       "AFSProcessShareSetInfo Completed request on pipe %wZ Class %08lX\n",
4240                       &Ccb->DirectoryCB->NameInformation.FileName,
4241                       ulFileInformationClass));
4242
4243 try_exit:
4244
4245         NOTHING;
4246     }
4247
4248     return ntStatus;
4249 }
4250
4251 NTSTATUS
4252 AFSProcessShareQueryInfo( IN IRP *Irp,
4253                           IN AFSFcb *Fcb,
4254                           IN AFSCcb *Ccb)
4255 {
4256
4257     UNREFERENCED_PARAMETER(Fcb);
4258     NTSTATUS ntStatus = STATUS_SUCCESS;
4259     PIO_STACK_LOCATION pIrpSp = IoGetCurrentIrpStackLocation( Irp);
4260     FILE_INFORMATION_CLASS ulFileInformationClass;
4261     void *pPipeInfo = NULL;
4262
4263     __Enter
4264     {
4265
4266         ulFileInformationClass = pIrpSp->Parameters.QueryFile.FileInformationClass;
4267
4268         AFSDbgTrace(( AFS_SUBSYSTEM_PIPE_PROCESSING,
4269                       AFS_TRACE_LEVEL_VERBOSE,
4270                       "AFSProcessShareQueryInfo On pipe %wZ Class %08lX\n",
4271                       &Ccb->DirectoryCB->NameInformation.FileName,
4272                       ulFileInformationClass));
4273
4274         pPipeInfo = AFSLockSystemBuffer( Irp,
4275                                          pIrpSp->Parameters.QueryFile.Length);
4276
4277         if( pPipeInfo == NULL)
4278         {
4279
4280             AFSDbgTrace(( AFS_SUBSYSTEM_PIPE_PROCESSING,
4281                           AFS_TRACE_LEVEL_ERROR,
4282                           "AFSProcessShareQueryInfo Failed to lock buffer on pipe %wZ\n",
4283                           &Ccb->DirectoryCB->NameInformation.FileName));
4284
4285             try_return( ntStatus = STATUS_INSUFFICIENT_RESOURCES);
4286         }
4287
4288         //
4289         // Send the request to the service
4290         //
4291
4292         ntStatus = AFSNotifyQueryPipeInfo( Ccb,
4293                                            (ULONG)ulFileInformationClass,
4294                                            pIrpSp->Parameters.QueryFile.Length,
4295                                            pPipeInfo,
4296                                            (ULONG *)&Irp->IoStatus.Information);
4297
4298         if( !NT_SUCCESS( ntStatus))
4299         {
4300
4301             AFSDbgTrace(( AFS_SUBSYSTEM_PIPE_PROCESSING,
4302                           AFS_TRACE_LEVEL_ERROR,
4303                           "AFSProcessShareQueryInfo Failed to send request to service on pipe %wZ Status %08lX\n",
4304                           &Ccb->DirectoryCB->NameInformation.FileName,
4305                           ntStatus));
4306
4307             try_return( ntStatus);
4308         }
4309
4310         AFSDbgTrace(( AFS_SUBSYSTEM_PIPE_PROCESSING,
4311                       AFS_TRACE_LEVEL_VERBOSE,
4312                       "AFSProcessShareQueryInfo Completed request on pipe %wZ Class %08lX\n",
4313                       &Ccb->DirectoryCB->NameInformation.FileName,
4314                       ulFileInformationClass));
4315
4316 try_exit:
4317
4318         NOTHING;
4319     }
4320
4321     return ntStatus;
4322 }
4323
4324 NTSTATUS
4325 AFSProcessPIOCtlQueryInfo( IN IRP *Irp,
4326                            IN AFSFcb *Fcb,
4327                            IN AFSCcb *Ccb,
4328                            IN OUT LONG *Length)
4329 {
4330
4331     UNREFERENCED_PARAMETER(Fcb);
4332     UNREFERENCED_PARAMETER(Ccb);
4333     NTSTATUS ntStatus = STATUS_SUCCESS;
4334     PIO_STACK_LOCATION pIrpSp = IoGetCurrentIrpStackLocation( Irp);
4335     FILE_INFORMATION_CLASS ulFileInformationClass;
4336
4337     __Enter
4338     {
4339
4340         ulFileInformationClass = pIrpSp->Parameters.QueryFile.FileInformationClass;
4341
4342         switch( ulFileInformationClass)
4343         {
4344
4345             case FileBasicInformation:
4346             {
4347
4348                 AFSDbgTrace(( AFS_SUBSYSTEM_PIOCTL_PROCESSING,
4349                               AFS_TRACE_LEVEL_VERBOSE,
4350                               "AFSProcessPIOCtlQueryInfo (FileBasicInformation)\n"));
4351
4352                 if ( *Length >= sizeof( FILE_BASIC_INFORMATION))
4353                 {
4354                     PFILE_BASIC_INFORMATION pBasic = (PFILE_BASIC_INFORMATION)Irp->AssociatedIrp.SystemBuffer;
4355
4356                     pBasic->CreationTime.QuadPart = 0;
4357                     pBasic->LastAccessTime.QuadPart = 0;
4358                     pBasic->ChangeTime.QuadPart = 0;
4359                     pBasic->LastWriteTime.QuadPart = 0;
4360                     pBasic->FileAttributes = FILE_ATTRIBUTE_HIDDEN | FILE_ATTRIBUTE_SYSTEM;
4361
4362                     *Length -= sizeof( FILE_BASIC_INFORMATION);
4363                 }
4364                 else
4365                 {
4366                     ntStatus = STATUS_BUFFER_TOO_SMALL;
4367                 }
4368
4369                 break;
4370             }
4371
4372             case FileStandardInformation:
4373             {
4374
4375                 AFSDbgTrace(( AFS_SUBSYSTEM_PIOCTL_PROCESSING,
4376                               AFS_TRACE_LEVEL_VERBOSE,
4377                               "AFSProcessPIOCtlQueryInfo (FileStandardInformation)\n"));
4378
4379                 if ( *Length >= sizeof( FILE_STANDARD_INFORMATION))
4380                 {
4381                     PFILE_STANDARD_INFORMATION pStandard = (PFILE_STANDARD_INFORMATION)Irp->AssociatedIrp.SystemBuffer;
4382
4383                     pStandard->NumberOfLinks = 1;
4384                     pStandard->DeletePending = 0;
4385                     pStandard->AllocationSize.QuadPart = 0;
4386                     pStandard->EndOfFile.QuadPart = 0;
4387                     pStandard->Directory = 0;
4388
4389                     *Length -= sizeof( FILE_STANDARD_INFORMATION);
4390                 }
4391                 else
4392                 {
4393                     ntStatus = STATUS_BUFFER_TOO_SMALL;
4394                 }
4395
4396                 break;
4397             }
4398
4399             case FileNormalizedNameInformation:
4400             case FileNameInformation:
4401             {
4402
4403                 ULONG ulCopyLength = 0;
4404                 AFSFcb *pFcb = NULL;
4405                 AFSCcb *pCcb = NULL;
4406                 USHORT usFullNameLength = 0;
4407                 PFILE_NAME_INFORMATION pNameInfo = (PFILE_NAME_INFORMATION)Irp->AssociatedIrp.SystemBuffer;
4408                 UNICODE_STRING uniName;
4409
4410                 AFSDbgTrace(( AFS_SUBSYSTEM_PIOCTL_PROCESSING,
4411                               AFS_TRACE_LEVEL_VERBOSE,
4412                               "AFSProcessPIOCtlQueryInfo (FileNameInformation)\n"));
4413
4414                 pFcb = (AFSFcb *)pIrpSp->FileObject->FsContext;
4415                 pCcb = (AFSCcb *)pIrpSp->FileObject->FsContext2;
4416
4417                 if( *Length < FIELD_OFFSET( FILE_NAME_INFORMATION, FileName))
4418                 {
4419                     ntStatus = STATUS_BUFFER_TOO_SMALL;
4420                     break;
4421                 }
4422
4423                 RtlZeroMemory( pNameInfo,
4424                                *Length);
4425
4426                 usFullNameLength = sizeof( WCHAR) +
4427                                             AFSServerName.Length +
4428                                             pCcb->FullFileName.Length;
4429
4430                 if( *Length >= (LONG)(FIELD_OFFSET( FILE_NAME_INFORMATION, FileName) + (LONG)usFullNameLength))
4431                 {
4432                     ulCopyLength = (LONG)usFullNameLength;
4433                 }
4434                 else
4435                 {
4436                     ulCopyLength = *Length - FIELD_OFFSET( FILE_NAME_INFORMATION, FileName);
4437                     ntStatus = STATUS_BUFFER_OVERFLOW;
4438                 }
4439
4440                 pNameInfo->FileNameLength = (ULONG)usFullNameLength;
4441
4442                 *Length -= FIELD_OFFSET( FILE_NAME_INFORMATION, FileName);
4443
4444                 if( ulCopyLength > 0)
4445                 {
4446
4447                     pNameInfo->FileName[ 0] = L'\\';
4448                     ulCopyLength -= sizeof( WCHAR);
4449
4450                     *Length -= sizeof( WCHAR);
4451
4452                     if( ulCopyLength >= AFSServerName.Length)
4453                     {
4454
4455                         RtlCopyMemory( &pNameInfo->FileName[ 1],
4456                                        AFSServerName.Buffer,
4457                                        AFSServerName.Length);
4458
4459                         ulCopyLength -= AFSServerName.Length;
4460                         *Length -= AFSServerName.Length;
4461
4462                         if( ulCopyLength >= pCcb->FullFileName.Length)
4463                         {
4464
4465                             RtlCopyMemory( &pNameInfo->FileName[ 1 + (AFSServerName.Length/sizeof( WCHAR))],
4466                                            pCcb->FullFileName.Buffer,
4467                                            pCcb->FullFileName.Length);
4468
4469                             ulCopyLength -= pCcb->FullFileName.Length;
4470                             *Length -= pCcb->FullFileName.Length;
4471
4472                             uniName.Length = (USHORT)pNameInfo->FileNameLength;
4473                             uniName.MaximumLength = uniName.Length;
4474                             uniName.Buffer = pNameInfo->FileName;
4475                         }
4476                         else
4477                         {
4478
4479                             RtlCopyMemory( &pNameInfo->FileName[ 1 + (AFSServerName.Length/sizeof( WCHAR))],
4480                                            pCcb->FullFileName.Buffer,
4481                                            ulCopyLength);
4482
4483                             *Length -= ulCopyLength;
4484
4485                             uniName.Length = (USHORT)(sizeof( WCHAR) + AFSServerName.Length + ulCopyLength);
4486                             uniName.MaximumLength = uniName.Length;
4487                             uniName.Buffer = pNameInfo->FileName;
4488                         }
4489
4490                         AFSDbgTrace(( AFS_SUBSYSTEM_PIOCTL_PROCESSING,
4491                                       AFS_TRACE_LEVEL_VERBOSE,
4492                                       "AFSProcessPIOCtlQueryInfo (FileNameInformation) Returning %wZ\n",
4493                                       &uniName));
4494                     }
4495                 }
4496
4497                 break;
4498             }
4499
4500             case FileInternalInformation:
4501             {
4502
4503                 PFILE_INTERNAL_INFORMATION pInternalInfo = (PFILE_INTERNAL_INFORMATION)Irp->AssociatedIrp.SystemBuffer;
4504
4505                 AFSDbgTrace(( AFS_SUBSYSTEM_PIOCTL_PROCESSING,
4506                               AFS_TRACE_LEVEL_VERBOSE,
4507                               "AFSProcessPIOCtlQueryInfo (FileInternalInformation)\n"));
4508
4509                 if( *Length >= sizeof( FILE_INTERNAL_INFORMATION))
4510                 {
4511
4512                     pInternalInfo->IndexNumber.HighPart = 0;
4513
4514                     pInternalInfo->IndexNumber.LowPart = 0;
4515
4516                     *Length -= sizeof( FILE_INTERNAL_INFORMATION);
4517                 }
4518                 else
4519                 {
4520
4521                     ntStatus = STATUS_BUFFER_TOO_SMALL;
4522                 }
4523
4524                 break;
4525             }
4526
4527             case FileAllInformation:
4528             {
4529                 ntStatus = STATUS_INVALID_PARAMETER;
4530
4531                 AFSDbgTrace(( AFS_SUBSYSTEM_PIOCTL_PROCESSING,
4532                               AFS_TRACE_LEVEL_WARNING,
4533                               "AFSProcessPIOCtlQueryInfo (FileAllInformation) Not Implemented\n"));
4534
4535                 break;
4536             }
4537
4538             case FileEaInformation:
4539             {
4540                 ntStatus = STATUS_INVALID_PARAMETER;
4541
4542                 AFSDbgTrace(( AFS_SUBSYSTEM_PIOCTL_PROCESSING,
4543                               AFS_TRACE_LEVEL_WARNING,
4544                               "AFSProcessPIOCtlQueryInfo (FileEaInformation) Not Implemented\n"));
4545
4546                 break;
4547             }
4548
4549             case FilePositionInformation:
4550             {
4551                 ntStatus = STATUS_INVALID_PARAMETER;
4552
4553                 AFSDbgTrace(( AFS_SUBSYSTEM_PIOCTL_PROCESSING,
4554                               AFS_TRACE_LEVEL_WARNING,
4555                               "AFSProcessPIOCtlQueryInfo (FilePositionInformation) Not Implemented\n"));
4556
4557                 break;
4558             }
4559
4560             case FileAlternateNameInformation:
4561             {
4562                 ntStatus = STATUS_INVALID_PARAMETER;
4563
4564                 AFSDbgTrace(( AFS_SUBSYSTEM_PIOCTL_PROCESSING,
4565                               AFS_TRACE_LEVEL_WARNING,
4566                               "AFSProcessPIOCtlQueryInfo (FileAlternateNameInformation) Not Implemented\n"));
4567
4568                 break;
4569             }
4570
4571             case FileNetworkOpenInformation:
4572             {
4573                 ntStatus = STATUS_INVALID_PARAMETER;
4574
4575                 AFSDbgTrace(( AFS_SUBSYSTEM_PIOCTL_PROCESSING,
4576                               AFS_TRACE_LEVEL_WARNING,
4577                               "AFSProcessPIOCtlQueryInfo (FileNetworkOpenInformation) Not Implemented\n"));
4578
4579                 break;
4580             }
4581
4582             case FileStreamInformation:
4583             {
4584                 ntStatus = STATUS_INVALID_PARAMETER;
4585
4586                 AFSDbgTrace(( AFS_SUBSYSTEM_PIOCTL_PROCESSING,
4587                               AFS_TRACE_LEVEL_WARNING,
4588                               "AFSProcessPIOCtlQueryInfo (FileStreamInformation) Not Implemented\n"));
4589
4590                 break;
4591             }
4592
4593             case FileAttributeTagInformation:
4594             {
4595                 ntStatus = STATUS_INVALID_PARAMETER;
4596
4597                 AFSDbgTrace(( AFS_SUBSYSTEM_PIOCTL_PROCESSING,
4598                               AFS_TRACE_LEVEL_WARNING,
4599                               "AFSProcessPIOCtlQueryInfo (FileAttributeTagInformation) Not Implemented\n"));
4600
4601                 break;
4602             }
4603
4604             case FileRemoteProtocolInformation:
4605             {
4606                 ntStatus = STATUS_INVALID_PARAMETER;
4607
4608                 AFSDbgTrace(( AFS_SUBSYSTEM_PIOCTL_PROCESSING,
4609                               AFS_TRACE_LEVEL_WARNING,
4610                               "AFSProcessPIOCtlQueryInfo (FileRemoteProtocolInformation) Not Implemented\n"));
4611
4612                 break;
4613             }
4614
4615             case FileNetworkPhysicalNameInformation:
4616             {
4617                 ntStatus = STATUS_INVALID_PARAMETER;
4618
4619                 AFSDbgTrace(( AFS_SUBSYSTEM_PIOCTL_PROCESSING,
4620                               AFS_TRACE_LEVEL_WARNING,
4621                               "AFSProcessPIOCtlQueryInfo (FileNetworkPhysicalNameInformation) Not Implemented\n"));
4622
4623                 break;
4624             }
4625
4626             default:
4627             {
4628                 ntStatus = STATUS_INVALID_PARAMETER;
4629
4630                 AFSDbgTrace(( AFS_SUBSYSTEM_PIOCTL_PROCESSING,
4631                               AFS_TRACE_LEVEL_WARNING,
4632                               "AFSProcessPIOCtlQueryInfo Not handling request %08lX\n",
4633                               ulFileInformationClass));
4634
4635                 break;
4636             }
4637         }
4638     }
4639
4640     AFSDbgTrace(( AFS_SUBSYSTEM_PIOCTL_PROCESSING,
4641                   AFS_TRACE_LEVEL_VERBOSE,
4642                   "AFSProcessPIOCtlQueryInfo ntStatus %08lX\n",
4643                   ntStatus));
4644
4645     return ntStatus;
4646 }
4647