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