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