Windows: Fix AFSSetBasicInfo attribute processing
[openafs.git] / src / WINNT / afsrdr / kernel / lib / AFSFileInfo.cpp
1 /*
2  * Copyright (c) 2008, 2009, 2010, 2011 Kernel Drivers, LLC.
3  * Copyright (c) 2009, 2010, 2011 Your File System, Inc.
4  * All rights reserved.
5  *
6  * Redistribution and use in source and binary forms, with or without
7  * modification, are permitted provided that the following conditions
8  * are met:
9  *
10  * - Redistributions of source code must retain the above copyright notice,
11  *   this list of conditions and the following disclaimer.
12  * - Redistributions in binary form must reproduce the above copyright
13  *   notice,
14  *   this list of conditions and the following disclaimer in the
15  *   documentation
16  *   and/or other materials provided with the distribution.
17  * - Neither the names of Kernel Drivers, LLC and Your File System, Inc.
18  *   nor the names of their contributors may be used to endorse or promote
19  *   products derived from this software without specific prior written
20  *   permission from Kernel Drivers, LLC and Your File System, Inc.
21  *
22  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
23  * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
24  * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
25  * PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER
26  * OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
27  * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
28  * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
29  * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
30  * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
31  * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
32  * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
33  */
34
35 //
36 // File: AFSFileInfo.cpp
37 //
38
39 #include "AFSCommon.h"
40
41 //
42 // Function: AFSQueryFileInfo
43 //
44 // Description:
45 //
46 //      This function is the dispatch handler for the IRP_MJ_QUERY_FILE_INFORMATION request
47 //
48 // Return:
49 //
50 //      A status is returned for the function
51 //
52
53 NTSTATUS
54 AFSQueryFileInfo( IN PDEVICE_OBJECT LibDeviceObject,
55                   IN PIRP Irp)
56 {
57
58     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
2068         pCcb->FileUnwindInfo.ChangeTime.QuadPart = (ULONGLONG)-1;
2069
2070         if( pBuffer->ChangeTime.QuadPart != (ULONGLONG)-1 &&
2071             pBuffer->ChangeTime.QuadPart != (ULONGLONG)0)
2072         {
2073
2074             pCcb->FileUnwindInfo.ChangeTime.QuadPart = DirectoryCB->ObjectInformation->ChangeTime.QuadPart;
2075
2076             DirectoryCB->ObjectInformation->ChangeTime.QuadPart = pBuffer->ChangeTime.QuadPart;
2077
2078             ulNotifyFilter |= FILE_NOTIFY_CHANGE_LAST_ACCESS;
2079
2080             SetFlag( DirectoryCB->ObjectInformation->Fcb->Flags, AFS_FCB_FLAG_FILE_MODIFIED | AFS_FCB_FLAG_UPDATE_CHANGE_TIME);
2081         }
2082
2083         if( ulNotifyFilter > 0)
2084         {
2085
2086             *bUpdateFileInfo = TRUE;
2087
2088             if( BooleanFlagOn( DirectoryCB->ObjectInformation->Flags, AFS_OBJECT_FLAGS_PARENT_FID))
2089             {
2090
2091                 AFSObjectInfoCB * pParentObjectInfo = AFSFindObjectInfo( DirectoryCB->ObjectInformation->VolumeCB,
2092                                                                          &DirectoryCB->ObjectInformation->ParentFileId,
2093                                                                          TRUE);
2094
2095                 if ( pParentObjectInfo != NULL)
2096                 {
2097                     AFSFsRtlNotifyFullReportChange( pParentObjectInfo,
2098                                                     pCcb,
2099                                                     (ULONG)ulNotifyFilter,
2100                                                     (ULONG)FILE_ACTION_MODIFIED);
2101
2102                     AFSReleaseObjectInfo( &pParentObjectInfo);
2103                 }
2104             }
2105         }
2106
2107 try_exit:
2108
2109         NOTHING;
2110     }
2111
2112     return ntStatus;
2113 }
2114
2115 NTSTATUS
2116 AFSSetDispositionInfo( IN PIRP Irp,
2117                        IN AFSDirectoryCB *DirectoryCB)
2118 {
2119     NTSTATUS ntStatus = STATUS_SUCCESS;
2120     PFILE_DISPOSITION_INFORMATION pBuffer;
2121     PIO_STACK_LOCATION pIrpSp = IoGetCurrentIrpStackLocation( Irp);
2122     AFSFcb *pFcb = NULL;
2123     AFSCcb *pCcb = NULL;
2124
2125     __Enter
2126     {
2127
2128         pBuffer = (PFILE_DISPOSITION_INFORMATION)Irp->AssociatedIrp.SystemBuffer;
2129
2130         pFcb = (AFSFcb *)pIrpSp->FileObject->FsContext;
2131
2132         pCcb = (AFSCcb *)pIrpSp->FileObject->FsContext2;
2133
2134         //
2135         // Can't delete the root
2136         //
2137
2138         if( pFcb->Header.NodeTypeCode == AFS_ROOT_FCB)
2139         {
2140
2141             AFSDbgTrace(( AFS_SUBSYSTEM_FILE_PROCESSING,
2142                           AFS_TRACE_LEVEL_ERROR,
2143                           "AFSSetDispositionInfo Attempt to delete root entry\n"));
2144
2145             try_return( ntStatus = STATUS_CANNOT_DELETE);
2146         }
2147
2148         //
2149         // If the file is read only then do not allow the delete
2150         //
2151
2152         if( BooleanFlagOn( DirectoryCB->ObjectInformation->FileAttributes, FILE_ATTRIBUTE_READONLY))
2153         {
2154
2155             AFSDbgTrace(( AFS_SUBSYSTEM_FILE_PROCESSING,
2156                           AFS_TRACE_LEVEL_ERROR,
2157                           "AFSSetDispositionInfo Attempt to delete read only entry %wZ\n",
2158                           &DirectoryCB->NameInformation.FileName));
2159
2160             try_return( ntStatus = STATUS_CANNOT_DELETE);
2161         }
2162
2163         if( pBuffer->DeleteFile)
2164         {
2165
2166             //
2167             // Check if the caller can delete the file
2168             //
2169
2170             ntStatus = AFSNotifyDelete( DirectoryCB,
2171                                         &pCcb->AuthGroup,
2172                                         TRUE);
2173
2174             if( !NT_SUCCESS( ntStatus))
2175             {
2176
2177                 AFSDbgTrace(( AFS_SUBSYSTEM_FILE_PROCESSING,
2178                               AFS_TRACE_LEVEL_ERROR,
2179                               "AFSSetDispositionInfo Cannot delete entry %wZ Status %08lX\n",
2180                               &DirectoryCB->NameInformation.FileName,
2181                               ntStatus));
2182
2183                 try_return( ntStatus);
2184             }
2185
2186             if( pFcb->Header.NodeTypeCode == AFS_DIRECTORY_FCB)
2187             {
2188
2189                 //
2190                 // Reduce the Link count in the object information block
2191                 // to correspond with the deletion of the directory entry.
2192                 //
2193
2194                 pFcb->ObjectInformation->Links--;
2195
2196                 //
2197                 // Check if this is a directory that there are not currently other opens
2198                 //
2199
2200                 if( pFcb->ObjectInformation->Specific.Directory.ChildOpenHandleCount > 0)
2201                 {
2202
2203                     AFSDbgTrace(( AFS_SUBSYSTEM_FILE_PROCESSING,
2204                                   AFS_TRACE_LEVEL_ERROR,
2205                                   "AFSSetDispositionInfo Attempt to delete directory %wZ with open %u handles\n",
2206                                   &DirectoryCB->NameInformation.FileName,
2207                                   pFcb->ObjectInformation->Specific.Directory.ChildOpenHandleCount));
2208
2209                     try_return( ntStatus = STATUS_DIRECTORY_NOT_EMPTY);
2210                 }
2211
2212                 //
2213                 // Make sure the directory is enumerated before checking to see if it is empty.
2214                 //
2215
2216                 if( !BooleanFlagOn( pFcb->ObjectInformation->Flags, AFS_OBJECT_FLAGS_DIRECTORY_ENUMERATED))
2217                 {
2218
2219                     AFSAcquireExcl( pFcb->ObjectInformation->Specific.Directory.DirectoryNodeHdr.TreeLock,
2220                                     TRUE);
2221
2222                     if( !BooleanFlagOn( pFcb->ObjectInformation->Flags, AFS_OBJECT_FLAGS_DIRECTORY_ENUMERATED))
2223                     {
2224
2225                         AFSDbgTrace(( AFS_SUBSYSTEM_FILE_PROCESSING,
2226                                       AFS_TRACE_LEVEL_VERBOSE,
2227                                       "AFSSetDispositionInfo Enumerating parent FID %08lX-%08lX-%08lX-%08lX\n",
2228                                       pFcb->ObjectInformation->FileId.Cell,
2229                                       pFcb->ObjectInformation->FileId.Volume,
2230                                       pFcb->ObjectInformation->FileId.Vnode,
2231                                       pFcb->ObjectInformation->FileId.Unique));
2232
2233                         ntStatus = AFSEnumerateDirectory( &pCcb->AuthGroup,
2234                                                           pFcb->ObjectInformation,
2235                                                           TRUE);
2236
2237                         if( !NT_SUCCESS( ntStatus))
2238                         {
2239
2240                             AFSReleaseResource( pFcb->ObjectInformation->Specific.Directory.DirectoryNodeHdr.TreeLock);
2241
2242                             AFSDbgTrace(( AFS_SUBSYSTEM_FILE_PROCESSING,
2243                                           AFS_TRACE_LEVEL_ERROR,
2244                                           "AFSSetDispositionInfo Failed to enumerate parent FID %08lX-%08lX-%08lX-%08lX Status %08lX\n",
2245                                           pFcb->ObjectInformation->FileId.Cell,
2246                                           pFcb->ObjectInformation->FileId.Volume,
2247                                           pFcb->ObjectInformation->FileId.Vnode,
2248                                           pFcb->ObjectInformation->FileId.Unique,
2249                                           ntStatus));
2250
2251                             try_return( ntStatus);
2252                         }
2253                     }
2254
2255                     AFSReleaseResource( pFcb->ObjectInformation->Specific.Directory.DirectoryNodeHdr.TreeLock);
2256                 }
2257
2258                 if( !AFSIsDirectoryEmptyForDelete( pFcb))
2259                 {
2260
2261                     AFSDbgTrace(( AFS_SUBSYSTEM_FILE_PROCESSING,
2262                                   AFS_TRACE_LEVEL_ERROR,
2263                                   "AFSSetDispositionInfo Attempt to delete non-empty directory %wZ\n",
2264                                   &DirectoryCB->NameInformation.FileName));
2265
2266                     try_return( ntStatus = STATUS_DIRECTORY_NOT_EMPTY);
2267                 }
2268
2269                 AFSDbgTrace(( AFS_SUBSYSTEM_FILE_PROCESSING,
2270                               AFS_TRACE_LEVEL_VERBOSE,
2271                               "AFSSetDispositionInfo Setting PENDING_DELETE on DirEntry  %p Name %wZ\n",
2272                               DirectoryCB,
2273                               &DirectoryCB->NameInformation.FileName));
2274
2275                 SetFlag( pCcb->DirectoryCB->Flags, AFS_DIR_ENTRY_PENDING_DELETE);
2276             }
2277             else if( pFcb->Header.NodeTypeCode == AFS_FILE_FCB)
2278             {
2279                 BOOLEAN bMmFlushed;
2280
2281                 AFSDbgTrace(( AFS_SUBSYSTEM_LOCK_PROCESSING,
2282                               AFS_TRACE_LEVEL_VERBOSE,
2283                               "AFSSetDispositionInfo Acquiring Fcb lock %p EXCL %08lX\n",
2284                               &pFcb->NPFcb->Resource,
2285                               PsGetCurrentThread()));
2286
2287                 AFSAcquireExcl( &pFcb->NPFcb->Resource,
2288                                 TRUE);
2289
2290                 AFSDbgTrace(( AFS_SUBSYSTEM_LOCK_PROCESSING|AFS_SUBSYSTEM_SECTION_OBJECT,
2291                               AFS_TRACE_LEVEL_VERBOSE,
2292                               "AFSSetDispositionInfo Acquiring Fcb SectionObject lock %p EXCL %08lX\n",
2293                               &pFcb->NPFcb->SectionObjectResource,
2294                               PsGetCurrentThread()));
2295
2296                 AFSAcquireExcl( &pFcb->NPFcb->SectionObjectResource,
2297                                 TRUE);
2298
2299                 __try
2300                 {
2301
2302                     //
2303                     // Attempt to flush any outstanding data
2304                     //
2305
2306                     bMmFlushed = MmFlushImageSection( &pFcb->NPFcb->SectionObjectPointers,
2307                                                       MmFlushForDelete);
2308
2309                     if ( bMmFlushed)
2310                     {
2311
2312                         //
2313                         // Set PENDING_DELETE before CcPurgeCacheSection to avoid a
2314                         // deadlock with Trend Micro's Enterprise anti-virus product
2315                         // which attempts to open the file which is being deleted.
2316                         //
2317
2318                         AFSDbgTrace(( AFS_SUBSYSTEM_FILE_PROCESSING,
2319                                       AFS_TRACE_LEVEL_VERBOSE,
2320                                       "AFSSetDispositionInfo Setting PENDING_DELETE on DirEntry %p Name %wZ\n",
2321                                       DirectoryCB,
2322                                       &DirectoryCB->NameInformation.FileName));
2323
2324                         SetFlag( pCcb->DirectoryCB->Flags, AFS_DIR_ENTRY_PENDING_DELETE);
2325
2326                         //
2327                         // Purge the cache as well
2328                         //
2329
2330                         if( pFcb->NPFcb->SectionObjectPointers.DataSectionObject != NULL)
2331                         {
2332
2333                             if ( !CcPurgeCacheSection( &pFcb->NPFcb->SectionObjectPointers,
2334                                                        NULL,
2335                                                        0,
2336                                                        TRUE))
2337                             {
2338
2339                                 SetFlag( pFcb->Flags, AFS_FCB_FLAG_PURGE_ON_CLOSE);
2340                             }
2341                         }
2342                     }
2343                 }
2344                 __except( EXCEPTION_EXECUTE_HANDLER)
2345                 {
2346
2347                     bMmFlushed = FALSE;
2348
2349                     ntStatus = GetExceptionCode();
2350
2351                     AFSDbgTrace(( 0,
2352                                   0,
2353                                   "EXCEPTION - AFSSetDispositionInfo MmFlushImageSection failed FID %08lX-%08lX-%08lX-%08lX Status 0x%08lX\n",
2354                                   pFcb->ObjectInformation->FileId.Cell,
2355                                   pFcb->ObjectInformation->FileId.Volume,
2356                                   pFcb->ObjectInformation->FileId.Vnode,
2357                                   pFcb->ObjectInformation->FileId.Unique,
2358                                   ntStatus));
2359                 }
2360
2361                 AFSDbgTrace(( AFS_SUBSYSTEM_LOCK_PROCESSING|AFS_SUBSYSTEM_SECTION_OBJECT,
2362                               AFS_TRACE_LEVEL_VERBOSE,
2363                               "AFSSetDispositionInfo Releasing Fcb SectionObject lock %p EXCL %08lX\n",
2364                               &pFcb->NPFcb->SectionObjectResource,
2365                               PsGetCurrentThread()));
2366
2367                 AFSReleaseResource( &pFcb->NPFcb->SectionObjectResource);
2368
2369                 AFSDbgTrace(( AFS_SUBSYSTEM_LOCK_PROCESSING,
2370                               AFS_TRACE_LEVEL_VERBOSE,
2371                               "AFSSetDispositionInfo Releasing Fcb lock %p EXCL %08lX\n",
2372                               &pFcb->NPFcb->Resource,
2373                               PsGetCurrentThread()));
2374
2375                 AFSReleaseResource( &pFcb->NPFcb->Resource);
2376
2377                 if ( !bMmFlushed)
2378                 {
2379
2380                     AFSDbgTrace(( AFS_SUBSYSTEM_FILE_PROCESSING,
2381                                   AFS_TRACE_LEVEL_ERROR,
2382                                   "AFSSetDispositionInfo Failed to flush image section for delete Entry %wZ\n",
2383                                   &DirectoryCB->NameInformation.FileName));
2384
2385                     try_return( ntStatus = STATUS_CANNOT_DELETE);
2386                 }
2387             }
2388             else if( pFcb->Header.NodeTypeCode == AFS_SYMBOLIC_LINK_FCB ||
2389                      pFcb->Header.NodeTypeCode == AFS_MOUNT_POINT_FCB ||
2390                      pFcb->Header.NodeTypeCode == AFS_DFS_LINK_FCB ||
2391                      pFcb->Header.NodeTypeCode == AFS_INVALID_FCB)
2392             {
2393
2394                 AFSDbgTrace(( AFS_SUBSYSTEM_FILE_PROCESSING,
2395                               AFS_TRACE_LEVEL_VERBOSE,
2396                               "AFSSetDispositionInfo Setting PENDING_DELETE on DirEntry %p Name %wZ\n",
2397                               DirectoryCB,
2398                               &DirectoryCB->NameInformation.FileName));
2399
2400                 SetFlag( pCcb->DirectoryCB->Flags, AFS_DIR_ENTRY_PENDING_DELETE);
2401             }
2402         }
2403         else
2404         {
2405
2406             ClearFlag( pCcb->DirectoryCB->Flags, AFS_DIR_ENTRY_PENDING_DELETE);
2407         }
2408
2409         //
2410         // OK, should be good to go, set the flag in the file object
2411         //
2412
2413         pIrpSp->FileObject->DeletePending = pBuffer->DeleteFile;
2414
2415 try_exit:
2416
2417         NOTHING;
2418     }
2419
2420     return ntStatus;
2421 }
2422
2423 NTSTATUS
2424 AFSSetFileLinkInfo( IN PIRP Irp)
2425 {
2426
2427     NTSTATUS ntStatus = STATUS_SUCCESS;
2428     AFSDeviceExt *pDeviceExt = (AFSDeviceExt *)AFSRDRDeviceObject->DeviceExtension;
2429     PIO_STACK_LOCATION pIrpSp = IoGetCurrentIrpStackLocation( Irp);
2430     PFILE_LINK_INFORMATION pFileLinkInfo = NULL;
2431     PFILE_OBJECT pSrcFileObj = NULL;
2432     PFILE_OBJECT pTargetFileObj = pIrpSp->Parameters.SetFile.FileObject;
2433     AFSFcb *pSrcFcb = NULL, *pTargetDcb = NULL;
2434     AFSCcb *pSrcCcb = NULL, *pTargetDirCcb = NULL;
2435     AFSObjectInfoCB *pSrcObject = NULL;
2436     AFSObjectInfoCB *pSrcParentObject = NULL, *pTargetParentObject = NULL;
2437     UNICODE_STRING uniSourceName, uniTargetName;
2438     UNICODE_STRING uniFullTargetName, uniTargetParentName;
2439     BOOLEAN bCommonParent = FALSE;
2440     AFSDirectoryCB *pTargetDirEntry = NULL;
2441     AFSDirectoryCB *pNewTargetDirEntry = NULL;
2442     ULONG ulTargetCRC;
2443     BOOLEAN bTargetEntryExists = FALSE;
2444     LONG lCount;
2445     BOOLEAN bReleaseTargetDirLock = FALSE;
2446     ULONG ulNotificationAction = 0, ulNotifyFilter = 0;
2447
2448     __Enter
2449     {
2450
2451         pSrcFileObj = pIrpSp->FileObject;
2452
2453         pSrcFcb = (AFSFcb *)pSrcFileObj->FsContext;
2454         pSrcCcb = (AFSCcb *)pSrcFileObj->FsContext2;
2455
2456         pSrcObject = pSrcFcb->ObjectInformation;
2457
2458         if ( BooleanFlagOn( pSrcObject->Flags, AFS_OBJECT_FLAGS_PARENT_FID))
2459         {
2460
2461             pSrcParentObject = AFSFindObjectInfo( pSrcObject->VolumeCB,
2462                                                   &pSrcObject->ParentFileId,
2463                                                   TRUE);
2464         }
2465
2466         if( pSrcParentObject == NULL)
2467         {
2468
2469             AFSDbgTrace(( AFS_SUBSYSTEM_FILE_PROCESSING,
2470                           AFS_TRACE_LEVEL_ERROR,
2471                           "AFSSetFileLinkInfo Unable to resolve SrcParentObject (INVALID_PARAMETER)\n"));
2472
2473             ASSERT( FALSE);
2474
2475             try_return( ntStatus = STATUS_INVALID_PARAMETER);
2476         }
2477
2478         pFileLinkInfo = (PFILE_LINK_INFORMATION)Irp->AssociatedIrp.SystemBuffer;
2479
2480         //
2481         // Perform some basic checks to ensure FS integrity
2482         //
2483
2484         if( pSrcFcb->Header.NodeTypeCode != AFS_FILE_FCB)
2485         {
2486
2487             AFSDbgTrace(( AFS_SUBSYSTEM_FILE_PROCESSING,
2488                           AFS_TRACE_LEVEL_ERROR,
2489                           "AFSSetFileLinkInfo Attempt to non-file (INVALID_PARAMETER)\n"));
2490
2491             try_return( ntStatus = STATUS_INVALID_PARAMETER);
2492         }
2493
2494         if( pTargetFileObj == NULL)
2495         {
2496
2497             if ( pFileLinkInfo->RootDirectory)
2498             {
2499
2500                 //
2501                 // The target directory is provided by HANDLE
2502                 // RootDirectory is only set when the target directory is not the same
2503                 // as the source directory.
2504                 //
2505                 // AFS only supports hard links within a single directory.
2506                 //
2507                 // The IOManager should translate any Handle to a FileObject for us.
2508                 // However, the failure to receive a FileObject is treated as a fatal
2509                 // error.
2510                 //
2511
2512                 AFSDbgTrace(( AFS_SUBSYSTEM_FILE_PROCESSING,
2513                               AFS_TRACE_LEVEL_ERROR,
2514                               "AFSSetFileLinkInfo Attempt to link %wZ to alternate directory by handle INVALID_PARAMETER\n",
2515                               &pSrcCcb->DirectoryCB->NameInformation.FileName));
2516
2517                 try_return( ntStatus = STATUS_INVALID_PARAMETER);
2518             }
2519             else
2520             {
2521
2522                 uniFullTargetName.Length = (USHORT)pFileLinkInfo->FileNameLength;
2523
2524                 uniFullTargetName.Buffer = (PWSTR)&pFileLinkInfo->FileName;
2525
2526                 AFSRetrieveFinalComponent( &uniFullTargetName,
2527                                            &uniTargetName);
2528
2529                 AFSRetrieveParentPath( &uniFullTargetName,
2530                                        &uniTargetParentName);
2531
2532                 if ( uniTargetParentName.Length == 0)
2533                 {
2534
2535                     //
2536                     // This is a simple rename. Here the target directory is the same as the source parent directory
2537                     // and the name is retrieved from the system buffer information
2538                     //
2539
2540                     pTargetParentObject = pSrcParentObject;
2541                 }
2542                 else
2543                 {
2544                     //
2545                     // uniTargetParentName contains the directory the renamed object
2546                     // will be moved to.  Must obtain the TargetParentObject.
2547                     //
2548
2549                     AFSDbgTrace(( AFS_SUBSYSTEM_FILE_PROCESSING,
2550                                   AFS_TRACE_LEVEL_ERROR,
2551                                   "AFSSetFileLinkInfo Attempt to link  %wZ to alternate directory %wZ (NOT_SAME_DEVICE)\n",
2552                                   &pSrcCcb->DirectoryCB->NameInformation.FileName,
2553                                   &uniFullTargetName));
2554
2555                     try_return( ntStatus = STATUS_NOT_SAME_DEVICE);
2556                 }
2557             }
2558
2559             pTargetDcb = pTargetParentObject->Fcb;
2560         }
2561         else
2562         {
2563
2564             //
2565             // So here we have the target directory taken from the targetfile object
2566             //
2567
2568             pTargetDcb = (AFSFcb *)pTargetFileObj->FsContext;
2569
2570             pTargetDirCcb = (AFSCcb *)pTargetFileObj->FsContext2;
2571
2572             pTargetParentObject = (AFSObjectInfoCB *)pTargetDcb->ObjectInformation;
2573
2574             //
2575             // Grab the target name which we setup in the IRP_MJ_CREATE handler. By how we set this up
2576             // it is only the target component of the rename operation
2577             //
2578
2579             uniTargetName = *((PUNICODE_STRING)&pTargetFileObj->FileName);
2580         }
2581
2582         //
2583         // The quick check to see if they are self linking.
2584         // Do the names match? Only do this where the parent directories are
2585         // the same
2586         //
2587
2588         if( pTargetParentObject == pSrcParentObject)
2589         {
2590
2591             if( FsRtlAreNamesEqual( &uniTargetName,
2592                                     &uniSourceName,
2593                                     FALSE,
2594                                     NULL))
2595             {
2596                 try_return( ntStatus = STATUS_SUCCESS);
2597             }
2598
2599             bCommonParent = TRUE;
2600         }
2601         else
2602         {
2603
2604             //
2605             // We do not allow cross-volume hard links
2606             //
2607
2608             if( pTargetParentObject->VolumeCB != pSrcObject->VolumeCB)
2609             {
2610
2611                 AFSDbgTrace(( AFS_SUBSYSTEM_FILE_PROCESSING,
2612                               AFS_TRACE_LEVEL_ERROR,
2613                               "AFSSetFileLinkInfo Attempt to link to different volume %wZ\n",
2614                               &pSrcCcb->DirectoryCB->NameInformation.FileName));
2615
2616                 try_return( ntStatus = STATUS_NOT_SAME_DEVICE);
2617             }
2618         }
2619
2620         ulTargetCRC = AFSGenerateCRC( &uniTargetName,
2621                                       FALSE);
2622
2623         AFSAcquireExcl( pTargetParentObject->Specific.Directory.DirectoryNodeHdr.TreeLock,
2624                         TRUE);
2625
2626         bReleaseTargetDirLock = TRUE;
2627
2628         AFSLocateCaseSensitiveDirEntry( pTargetParentObject->Specific.Directory.DirectoryNodeHdr.CaseSensitiveTreeHead,
2629                                         ulTargetCRC,
2630                                         &pTargetDirEntry);
2631
2632         if( pTargetDirEntry == NULL)
2633         {
2634
2635             //
2636             // Missed so perform a case insensitive lookup
2637             //
2638
2639             ulTargetCRC = AFSGenerateCRC( &uniTargetName,
2640                                           TRUE);
2641
2642             AFSLocateCaseInsensitiveDirEntry( pTargetParentObject->Specific.Directory.DirectoryNodeHdr.CaseInsensitiveTreeHead,
2643                                               ulTargetCRC,
2644                                               &pTargetDirEntry);
2645         }
2646
2647         if ( !BooleanFlagOn( pDeviceExt->DeviceFlags, AFS_DEVICE_FLAG_DISABLE_SHORTNAMES) &&
2648              pTargetDirEntry == NULL && RtlIsNameLegalDOS8Dot3( &uniTargetName,
2649                                                                 NULL,
2650                                                                 NULL))
2651         {
2652             //
2653             // Try the short name
2654             //
2655             AFSLocateShortNameDirEntry( pTargetParentObject->Specific.Directory.ShortNameTree,
2656                                         ulTargetCRC,
2657                                         &pTargetDirEntry);
2658         }
2659
2660         //
2661         // Increment our ref count on the dir entry
2662         //
2663
2664         if( pTargetDirEntry != NULL)
2665         {
2666
2667             ASSERT( BooleanFlagOn( pTargetDirEntry->ObjectInformation->Flags, AFS_OBJECT_FLAGS_PARENT_FID) &&
2668                     AFSIsEqualFID( &pTargetParentObject->FileId, &pTargetDirEntry->ObjectInformation->ParentFileId));
2669
2670             lCount = InterlockedIncrement( &pTargetDirEntry->DirOpenReferenceCount);
2671
2672             AFSDbgTrace(( AFS_SUBSYSTEM_DIRENTRY_REF_COUNTING,
2673                           AFS_TRACE_LEVEL_VERBOSE,
2674                           "AFSSetFileLinkInfo Increment count on %wZ DE %p Ccb %p Cnt %d\n",
2675                           &pTargetDirEntry->NameInformation.FileName,
2676                           pTargetDirEntry,
2677                           pSrcCcb,
2678                           lCount));
2679
2680             ASSERT( lCount >= 0);
2681
2682             if( !pFileLinkInfo->ReplaceIfExists)
2683             {
2684
2685                 AFSDbgTrace(( AFS_SUBSYSTEM_FILE_PROCESSING,
2686                               AFS_TRACE_LEVEL_ERROR,
2687                               "AFSSetFileLinkInfo Attempt to link with target collision %wZ Target %wZ\n",
2688                               &pSrcCcb->DirectoryCB->NameInformation.FileName,
2689                               &pTargetDirEntry->NameInformation.FileName));
2690
2691                 try_return( ntStatus = STATUS_OBJECT_NAME_COLLISION);
2692             }
2693
2694             AFSDbgTrace(( AFS_SUBSYSTEM_FILE_PROCESSING | AFS_SUBSYSTEM_DIRENTRY_REF_COUNTING,
2695                           AFS_TRACE_LEVEL_ERROR,
2696                           "AFSSetFileLinkInfo Target %wZ exists DE %p Count %d, performing delete of target\n",
2697                           &pTargetDirEntry->NameInformation.FileName,
2698                           pTargetDirEntry,
2699                           lCount));
2700
2701             //
2702             // Pull the directory entry from the parent
2703             //
2704
2705             AFSRemoveDirNodeFromParent( pTargetParentObject,
2706                                         pTargetDirEntry,
2707                                         FALSE);
2708
2709             bTargetEntryExists = TRUE;
2710         }
2711         else
2712         {
2713             AFSDbgTrace(( AFS_SUBSYSTEM_FILE_PROCESSING,
2714                           AFS_TRACE_LEVEL_VERBOSE,
2715                           "AFSSetFileLinkInfo Target does NOT exist, normal linking\n"));
2716         }
2717
2718         //
2719         // OK, this is a simple rename. Issue the rename
2720         // request to the service.
2721         //
2722
2723         ntStatus = AFSNotifyHardLink( pSrcObject,
2724                                       &pSrcCcb->AuthGroup,
2725                                       pSrcParentObject,
2726                                       pTargetDcb->ObjectInformation,
2727                                       pSrcCcb->DirectoryCB,
2728                                       &uniTargetName,
2729                                       pFileLinkInfo->ReplaceIfExists,
2730                                       &pNewTargetDirEntry);
2731
2732         if( ntStatus != STATUS_REPARSE &&
2733             !NT_SUCCESS( ntStatus))
2734         {
2735
2736             AFSDbgTrace(( AFS_SUBSYSTEM_FILE_PROCESSING,
2737                           AFS_TRACE_LEVEL_ERROR,
2738                           "AFSSetFileLinkInfo Failed link of %wZ to target %wZ Status %08lX\n",
2739                           &pSrcCcb->DirectoryCB->NameInformation.FileName,
2740                           &uniTargetName,
2741                           ntStatus));
2742
2743             try_return( ntStatus);
2744         }
2745
2746         if ( ntStatus != STATUS_REPARSE)
2747         {
2748
2749             AFSInsertDirectoryNode( pTargetDcb->ObjectInformation,
2750                                     pNewTargetDirEntry,
2751                                     TRUE);
2752         }
2753
2754         //
2755         // Send notification for the target link file
2756         //
2757
2758         if( bTargetEntryExists || pNewTargetDirEntry)
2759         {
2760
2761             ulNotificationAction = FILE_ACTION_MODIFIED;
2762         }
2763         else
2764         {
2765
2766             ulNotificationAction = FILE_ACTION_ADDED;
2767         }
2768
2769         AFSFsRtlNotifyFullReportChange( pTargetParentObject,
2770                                         pSrcCcb,
2771                                         (ULONG)ulNotifyFilter,
2772                                         (ULONG)ulNotificationAction);
2773
2774       try_exit:
2775
2776         if( !NT_SUCCESS( ntStatus))
2777         {
2778
2779             if( bTargetEntryExists)
2780             {
2781
2782                 AFSInsertDirectoryNode( pTargetParentObject,
2783                                         pTargetDirEntry,
2784                                         FALSE);
2785             }
2786         }
2787
2788         if( pTargetDirEntry != NULL)
2789         {
2790
2791             //
2792             // Release DirOpenReferenceCount obtained above
2793             //
2794
2795             lCount = InterlockedDecrement( &pTargetDirEntry->DirOpenReferenceCount);
2796
2797             AFSDbgTrace(( AFS_SUBSYSTEM_DIRENTRY_REF_COUNTING,
2798                           AFS_TRACE_LEVEL_VERBOSE,
2799                           "AFSSetFileLinkInfo Decrement count on %wZ DE %p Ccb %p Cnt %d\n",
2800                           &pTargetDirEntry->NameInformation.FileName,
2801                           pTargetDirEntry,
2802                           pSrcCcb,
2803                           lCount));
2804
2805             ASSERT( lCount >= 0);
2806         }
2807
2808         if( pNewTargetDirEntry != NULL)
2809         {
2810
2811             //
2812             // Release DirOpenReferenceCount obtained from AFSNotifyHardLink
2813             //
2814
2815             lCount = InterlockedDecrement( &pNewTargetDirEntry->DirOpenReferenceCount);
2816
2817             AFSDbgTrace(( AFS_SUBSYSTEM_DIRENTRY_REF_COUNTING,
2818                           AFS_TRACE_LEVEL_VERBOSE,
2819                           "AFSSetFileLinkInfo Decrement count on %wZ DE %p Ccb %p Cnt %d\n",
2820                           &pNewTargetDirEntry->NameInformation.FileName,
2821                           pNewTargetDirEntry,
2822                           pSrcCcb,
2823                           lCount));
2824
2825             ASSERT( lCount >= 0);
2826         }
2827
2828         if( bReleaseTargetDirLock)
2829         {
2830
2831             AFSReleaseResource( pTargetParentObject->Specific.Directory.DirectoryNodeHdr.TreeLock);
2832         }
2833
2834         if ( pSrcParentObject != NULL)
2835         {
2836
2837             AFSReleaseObjectInfo( &pSrcParentObject);
2838         }
2839
2840         //
2841         // No need to release pTargetParentObject as it is either a copy of pSrcParentObject
2842         // or (AFSFcb *)pTargetFileObj->FsContext->ObjectInformation
2843         //
2844
2845         pTargetParentObject = NULL;
2846     }
2847
2848     return ntStatus;
2849 }
2850
2851 NTSTATUS
2852 AFSSetRenameInfo( IN PIRP Irp)
2853 {
2854
2855     NTSTATUS ntStatus = STATUS_SUCCESS;
2856     AFSDeviceExt *pDeviceExt = (AFSDeviceExt *)AFSRDRDeviceObject->DeviceExtension;
2857     PIO_STACK_LOCATION pIrpSp = IoGetCurrentIrpStackLocation( Irp);
2858     AFSFcb *pSrcFcb = NULL, *pTargetDcb = NULL, *pTargetFcb = NULL;
2859     AFSCcb *pSrcCcb = NULL, *pTargetDirCcb = NULL;
2860     PFILE_OBJECT pSrcFileObj = pIrpSp->FileObject;
2861     PFILE_OBJECT pTargetFileObj = pIrpSp->Parameters.SetFile.FileObject;
2862     PFILE_OBJECT pTargetParentFileObj = NULL;
2863     PFILE_RENAME_INFORMATION pRenameInfo = NULL;
2864     UNICODE_STRING uniTargetName, uniSourceName, uniTargetParentName;
2865     BOOLEAN bReplaceIfExists = FALSE;
2866     UNICODE_STRING uniShortName;
2867     AFSDirectoryCB *pTargetDirEntry = NULL;
2868     ULONG ulTargetCRC = 0;
2869     BOOLEAN bTargetEntryExists = FALSE;
2870     AFSObjectInfoCB *pSrcObject = NULL;
2871     AFSObjectInfoCB *pSrcParentObject = NULL, *pTargetParentObject = NULL;
2872     AFSFileID stNewFid;
2873     ULONG ulNotificationAction = 0, ulNotifyFilter = 0;
2874     UNICODE_STRING uniFullTargetName;
2875     BOOLEAN bCommonParent = FALSE;
2876     BOOLEAN bReleaseTargetDirLock = FALSE;
2877     BOOLEAN bReleaseSourceDirLock = FALSE;
2878     BOOLEAN bDereferenceTargetParentObject = FALSE;
2879     PERESOURCE  pSourceDirLock = NULL;
2880     LONG lCount;
2881
2882     __Enter
2883     {
2884
2885         bReplaceIfExists = pIrpSp->Parameters.SetFile.ReplaceIfExists;
2886
2887         pRenameInfo = (PFILE_RENAME_INFORMATION)Irp->AssociatedIrp.SystemBuffer;
2888
2889         pSrcFcb = (AFSFcb *)pSrcFileObj->FsContext;
2890         pSrcCcb = (AFSCcb *)pSrcFileObj->FsContext2;
2891
2892         pSrcObject = pSrcFcb->ObjectInformation;
2893
2894         if ( BooleanFlagOn( pSrcObject->Flags, AFS_OBJECT_FLAGS_PARENT_FID))
2895         {
2896
2897             pSrcParentObject = AFSFindObjectInfo( pSrcObject->VolumeCB,
2898                                                   &pSrcObject->ParentFileId,
2899                                                   TRUE);
2900         }
2901
2902         if( pSrcParentObject == NULL)
2903         {
2904
2905             AFSDbgTrace(( AFS_SUBSYSTEM_FILE_PROCESSING,
2906                           AFS_TRACE_LEVEL_ERROR,
2907                           "AFSSetRenameInfo Unable to resolve SrcParentObject (INVALID_PARAMETER)\n"));
2908
2909             ASSERT( FALSE);
2910
2911             try_return( ntStatus = STATUS_INVALID_PARAMETER);
2912         }
2913
2914         //
2915         // Perform some basic checks to ensure FS integrity
2916         //
2917
2918         if( pSrcFcb->Header.NodeTypeCode == AFS_ROOT_FCB)
2919         {
2920
2921             //
2922             // Can't rename the root directory
2923             //
2924
2925             AFSDbgTrace(( AFS_SUBSYSTEM_FILE_PROCESSING,
2926                           AFS_TRACE_LEVEL_ERROR,
2927                           "AFSSetRenameInfo Attempt to rename root entry\n"));
2928
2929             try_return( ntStatus = STATUS_INVALID_PARAMETER);
2930         }
2931
2932         if( pSrcFcb->Header.NodeTypeCode == AFS_DIRECTORY_FCB)
2933         {
2934
2935             //
2936             // If there are any open children then fail the rename
2937             //
2938
2939             if( pSrcObject->Specific.Directory.ChildOpenHandleCount > 0)
2940             {
2941
2942                 AFSDbgTrace(( AFS_SUBSYSTEM_FILE_PROCESSING,
2943                               AFS_TRACE_LEVEL_ERROR,
2944                               "AFSSetRenameInfo Attempt to rename directory with open children %wZ\n",
2945                               &pSrcCcb->DirectoryCB->NameInformation.FileName));
2946
2947                 try_return( ntStatus = STATUS_ACCESS_DENIED);
2948             }
2949         }
2950
2951
2952         //
2953         // Extract off the final component name from the Fcb
2954         //
2955
2956         uniSourceName.Length = (USHORT)pSrcCcb->DirectoryCB->NameInformation.FileName.Length;
2957         uniSourceName.MaximumLength = uniSourceName.Length;
2958
2959         uniSourceName.Buffer = pSrcCcb->DirectoryCB->NameInformation.FileName.Buffer;
2960
2961         //
2962         // Resolve the target fileobject
2963         //
2964
2965         if( pTargetFileObj == NULL)
2966         {
2967
2968             if ( pRenameInfo->RootDirectory)
2969             {
2970
2971                 AFSDbgTrace(( AFS_SUBSYSTEM_FILE_PROCESSING,
2972                               AFS_TRACE_LEVEL_ERROR,
2973                               "AFSSetRenameInfo Handle provided but no FileObject ntStatus INVALID_PARAMETER\n"));
2974
2975                 try_return( ntStatus = STATUS_INVALID_PARAMETER);
2976             }
2977             else
2978             {
2979
2980                 uniFullTargetName.Length = (USHORT)pRenameInfo->FileNameLength;
2981
2982                 uniFullTargetName.Buffer = (PWSTR)&pRenameInfo->FileName;
2983
2984                 AFSRetrieveFinalComponent( &uniFullTargetName,
2985                                            &uniTargetName);
2986
2987                 AFSRetrieveParentPath( &uniFullTargetName,
2988                                        &uniTargetParentName);
2989
2990                 if ( uniTargetParentName.Length == 0)
2991                 {
2992
2993                     //
2994                     // This is a simple rename. Here the target directory is the same as the source parent directory
2995                     // and the name is retrieved from the system buffer information
2996                     //
2997
2998                     pTargetParentObject = pSrcParentObject;
2999                 }
3000                 else
3001                 {
3002                     //
3003                     // uniTargetParentName contains the directory the renamed object
3004                     // will be moved to.  Must obtain the TargetParentObject.
3005                     //
3006
3007                     AFSDbgTrace(( AFS_SUBSYSTEM_FILE_PROCESSING,
3008                                   AFS_TRACE_LEVEL_ERROR,
3009                                   "AFSSetRenameInfo Attempt to move %wZ to %wZ -- not yet supported (NOT_SAME_DEVICE)\n",
3010                                   &pSrcCcb->DirectoryCB->NameInformation.FileName,
3011                                   &uniFullTargetName));
3012
3013                     try_return( ntStatus = STATUS_NOT_SAME_DEVICE);
3014                 }
3015             }
3016
3017             pTargetDcb = pTargetParentObject->Fcb;
3018         }
3019         else
3020         {
3021
3022             //
3023             // So here we have the target directory taken from the targetfile object
3024             //
3025
3026             pTargetDcb = (AFSFcb *)pTargetFileObj->FsContext;
3027
3028             pTargetDirCcb = (AFSCcb *)pTargetFileObj->FsContext2;
3029
3030             pTargetParentObject = (AFSObjectInfoCB *)pTargetDcb->ObjectInformation;
3031
3032             //
3033             // Grab the target name which we setup in the IRP_MJ_CREATE handler. By how we set this up
3034             // it is only the target component of the rename operation
3035             //
3036
3037             uniTargetName = *((PUNICODE_STRING)&pTargetFileObj->FileName);
3038         }
3039
3040         //
3041         // The quick check to see if they are not really performing a rename
3042         // Do the names match? Only do this where the parent directories are
3043         // the same
3044         //
3045
3046         if( pTargetParentObject == pSrcParentObject)
3047         {
3048
3049             if( FsRtlAreNamesEqual( &uniTargetName,
3050                                     &uniSourceName,
3051                                     FALSE,
3052                                     NULL))
3053             {
3054                 try_return( ntStatus = STATUS_SUCCESS);
3055             }
3056
3057             bCommonParent = TRUE;
3058         }
3059         else
3060         {
3061
3062             bCommonParent = FALSE;
3063         }
3064
3065         //
3066         // We do not allow cross-volume renames to occur
3067         //
3068
3069         if( pTargetParentObject->VolumeCB != pSrcObject->VolumeCB)
3070         {
3071
3072             AFSDbgTrace(( AFS_SUBSYSTEM_FILE_PROCESSING,
3073                           AFS_TRACE_LEVEL_ERROR,
3074                           "AFSSetRenameInfo Attempt to rename directory to different volume %wZ\n",
3075                           &pSrcCcb->DirectoryCB->NameInformation.FileName));
3076
3077             try_return( ntStatus = STATUS_NOT_SAME_DEVICE);
3078         }
3079
3080         ulTargetCRC = AFSGenerateCRC( &uniTargetName,
3081                                       FALSE);
3082
3083         AFSAcquireExcl( pTargetParentObject->Specific.Directory.DirectoryNodeHdr.TreeLock,
3084                         TRUE);
3085
3086         bReleaseTargetDirLock = TRUE;
3087
3088         if( pTargetParentObject != pSrcParentObject)
3089         {
3090             AFSAcquireExcl( pSrcParentObject->Specific.Directory.DirectoryNodeHdr.TreeLock,
3091                             TRUE);
3092
3093             bReleaseSourceDirLock = TRUE;
3094
3095             pSourceDirLock = pSrcParentObject->Specific.Directory.DirectoryNodeHdr.TreeLock;
3096         }
3097
3098         AFSLocateCaseSensitiveDirEntry( pTargetParentObject->Specific.Directory.DirectoryNodeHdr.CaseSensitiveTreeHead,
3099                                         ulTargetCRC,
3100                                         &pTargetDirEntry);
3101
3102         if( pTargetDirEntry == NULL)
3103         {
3104
3105             //
3106             // Missed so perform a case insensitive lookup
3107             //
3108
3109             ulTargetCRC = AFSGenerateCRC( &uniTargetName,
3110                                           TRUE);
3111
3112             AFSLocateCaseInsensitiveDirEntry( pTargetParentObject->Specific.Directory.DirectoryNodeHdr.CaseInsensitiveTreeHead,
3113                                               ulTargetCRC,
3114                                               &pTargetDirEntry);
3115         }
3116
3117         if ( !BooleanFlagOn( pDeviceExt->DeviceFlags, AFS_DEVICE_FLAG_DISABLE_SHORTNAMES) &&
3118              pTargetDirEntry == NULL && RtlIsNameLegalDOS8Dot3( &uniTargetName,
3119                                                                NULL,
3120                                                                NULL))
3121         {
3122             //
3123             // Try the short name
3124             //
3125             AFSLocateShortNameDirEntry( pTargetParentObject->Specific.Directory.ShortNameTree,
3126                                         ulTargetCRC,
3127                                         &pTargetDirEntry);
3128         }
3129
3130         //
3131         // Increment our ref count on the dir entry
3132         //
3133
3134         if( pTargetDirEntry != NULL)
3135         {
3136
3137             ASSERT( BooleanFlagOn( pTargetDirEntry->ObjectInformation->Flags, AFS_OBJECT_FLAGS_PARENT_FID) &&
3138                     AFSIsEqualFID( &pTargetParentObject->FileId, &pTargetDirEntry->ObjectInformation->ParentFileId));
3139
3140             lCount = InterlockedIncrement( &pTargetDirEntry->DirOpenReferenceCount);
3141
3142             AFSDbgTrace(( AFS_SUBSYSTEM_DIRENTRY_REF_COUNTING,
3143                           AFS_TRACE_LEVEL_VERBOSE,
3144                           "AFSSetRenameInfo Increment count on %wZ DE %p Ccb %p Cnt %d\n",
3145                           &pTargetDirEntry->NameInformation.FileName,
3146                           pTargetDirEntry,
3147                           pSrcCcb,
3148                           lCount));
3149
3150             ASSERT( lCount >= 0);
3151
3152             if( !bReplaceIfExists)
3153             {
3154
3155                 AFSDbgTrace(( AFS_SUBSYSTEM_FILE_PROCESSING,
3156                               AFS_TRACE_LEVEL_ERROR,
3157                               "AFSSetRenameInfo Attempt to rename directory with target collision %wZ Target %wZ\n",
3158                               &pSrcCcb->DirectoryCB->NameInformation.FileName,
3159                               &pTargetDirEntry->NameInformation.FileName));
3160
3161                 try_return( ntStatus = STATUS_OBJECT_NAME_COLLISION);
3162             }
3163
3164             AFSDbgTrace(( AFS_SUBSYSTEM_FILE_PROCESSING | AFS_SUBSYSTEM_DIRENTRY_REF_COUNTING,
3165                           AFS_TRACE_LEVEL_ERROR,
3166                           "AFSSetRenameInfo Target %wZ exists DE %p Count %d, performing delete of target\n",
3167                           &pTargetDirEntry->NameInformation.FileName,
3168                           pTargetDirEntry,
3169                           lCount));
3170
3171             //
3172             // Pull the directory entry from the parent
3173             //
3174
3175             AFSRemoveDirNodeFromParent( pTargetParentObject,
3176                                         pTargetDirEntry,
3177                                         FALSE);
3178
3179             bTargetEntryExists = TRUE;
3180         }
3181         else
3182         {
3183             AFSDbgTrace(( AFS_SUBSYSTEM_FILE_PROCESSING,
3184                           AFS_TRACE_LEVEL_VERBOSE,
3185                           "AFSSetRenameInfo Target does NOT exist, normal rename\n"));
3186         }
3187
3188         //
3189         // We need to remove the DirEntry from the parent node, update the index
3190         // and reinsert it into the parent tree. Note that for entries with the
3191         // same parent we do not pull the node from the enumeration list
3192         //
3193
3194         AFSRemoveDirNodeFromParent( pSrcParentObject,
3195                                     pSrcCcb->DirectoryCB,
3196                                     !bCommonParent);
3197
3198         //
3199         // OK, this is a simple rename. Issue the rename
3200         // request to the service.
3201         //
3202
3203         ntStatus = AFSNotifyRename( pSrcObject,
3204                                     &pSrcCcb->AuthGroup,
3205                                     pSrcParentObject,
3206                                     pTargetDcb->ObjectInformation,
3207                                     pSrcCcb->DirectoryCB,
3208             &n