Windows: FileInfo too small INFO_LENGTH_MISMATCH
[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_INFO_LENGTH_MISMATCH);
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_INFO_LENGTH_MISMATCH);
279                 }
280
281                 lLength -= sizeof( FILE_MODE_INFORMATION);
282
283                 if( lLength < sizeof( FILE_ALIGNMENT_INFORMATION))
284                 {
285                     try_return( ntStatus = STATUS_INFO_LENGTH_MISMATCH);
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_INFO_LENGTH_MISMATCH;
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         ntStatus = STATUS_SUCCESS;
927     }
928
929     return ntStatus;
930 }
931
932 NTSTATUS
933 AFSQueryStandardInfo( IN PIRP Irp,
934                       IN AFSDirectoryCB *DirectoryCB,
935                       IN OUT PFILE_STANDARD_INFORMATION Buffer,
936                       IN OUT PLONG Length)
937 {
938
939     NTSTATUS ntStatus = STATUS_INFO_LENGTH_MISMATCH;
940     AFSFcb *pFcb = NULL;
941     AFSCcb *pCcb = NULL;
942     PIO_STACK_LOCATION pIrpSp = IoGetCurrentIrpStackLocation( Irp);
943     AFSFileInfoCB stFileInfo;
944     AFSDirectoryCB *pParentDirectoryCB = NULL;
945     UNICODE_STRING uniParentPath;
946     ULONG ulFileAttribs = 0;
947
948     if( *Length >= sizeof( FILE_STANDARD_INFORMATION))
949     {
950
951         pFcb = (AFSFcb *)pIrpSp->FileObject->FsContext;
952         pCcb = (AFSCcb *)pIrpSp->FileObject->FsContext2;
953
954         RtlZeroMemory( Buffer,
955                        *Length);
956
957         Buffer->NumberOfLinks = 1;
958         Buffer->DeletePending = BooleanFlagOn( pCcb->DirectoryCB->Flags, AFS_DIR_ENTRY_PENDING_DELETE);
959
960         Buffer->AllocationSize.QuadPart = (ULONGLONG)((DirectoryCB->ObjectInformation->AllocationSize.QuadPart/PAGE_SIZE) + 1) * PAGE_SIZE;
961
962         Buffer->EndOfFile = DirectoryCB->ObjectInformation->EndOfFile;
963
964         ulFileAttribs = DirectoryCB->ObjectInformation->FileAttributes;
965
966         if( DirectoryCB->ObjectInformation->FileType == AFS_FILE_TYPE_SYMLINK)
967         {
968
969             pParentDirectoryCB = AFSGetParentEntry( pCcb->NameArray);
970
971             AFSRetrieveParentPath( &pCcb->FullFileName,
972                                    &uniParentPath);
973
974             RtlZeroMemory( &stFileInfo,
975                            sizeof( AFSFileInfoCB));
976
977             //
978             // Can't hold the Fcb while evaluating the path, leads to lock inversion
979             //
980
981             AFSReleaseResource( &pFcb->NPFcb->Resource);
982
983             //
984             // Its a reparse point regardless of whether or not the
985             // file attributes can be retrieved.
986             //
987
988             if ( ulFileAttribs == FILE_ATTRIBUTE_NORMAL)
989             {
990
991                 ulFileAttribs = FILE_ATTRIBUTE_REPARSE_POINT;
992             }
993             else
994             {
995
996                 ulFileAttribs |= FILE_ATTRIBUTE_REPARSE_POINT;
997             }
998
999             if( NT_SUCCESS( AFSRetrieveFileAttributes( pParentDirectoryCB,
1000                                                        DirectoryCB,
1001                                                        &uniParentPath,
1002                                                        pCcb->NameArray,
1003                                                        &pCcb->AuthGroup,
1004                                                        &stFileInfo)))
1005             {
1006
1007                 if ( stFileInfo.FileAttributes & FILE_ATTRIBUTE_DIRECTORY)
1008                 {
1009
1010                     ulFileAttribs |= FILE_ATTRIBUTE_DIRECTORY;
1011                 }
1012             }
1013
1014             AFSAcquireShared( &pFcb->NPFcb->Resource,
1015                               TRUE);
1016         }
1017
1018         AFSDbgTrace(( AFS_SUBSYSTEM_FILE_PROCESSING,
1019                       AFS_TRACE_LEVEL_VERBOSE_2,
1020                       "AFSQueryStandardInfo %wZ Type 0x%x Attrib 0x%x -> 0x%x\n",
1021                       &pCcb->DirectoryCB->NameInformation.FileName,
1022                       pFcb->ObjectInformation->FileType,
1023                       pFcb->ObjectInformation->FileAttributes,
1024                       ulFileAttribs));
1025
1026         Buffer->Directory = BooleanFlagOn( ulFileAttribs, FILE_ATTRIBUTE_DIRECTORY);
1027
1028         *Length -= sizeof( FILE_STANDARD_INFORMATION);
1029
1030         ntStatus = STATUS_SUCCESS;
1031     }
1032
1033     return ntStatus;
1034 }
1035
1036 NTSTATUS
1037 AFSQueryInternalInfo( IN PIRP Irp,
1038                       IN AFSFcb *Fcb,
1039                       IN OUT PFILE_INTERNAL_INFORMATION Buffer,
1040                       IN OUT PLONG Length)
1041 {
1042
1043     UNREFERENCED_PARAMETER(Irp);
1044     NTSTATUS ntStatus = STATUS_INFO_LENGTH_MISMATCH;
1045
1046     if( *Length >= sizeof( FILE_INTERNAL_INFORMATION))
1047     {
1048
1049         Buffer->IndexNumber.HighPart = Fcb->ObjectInformation->FileId.Vnode;
1050
1051         Buffer->IndexNumber.LowPart = Fcb->ObjectInformation->FileId.Unique;
1052
1053         *Length -= sizeof( FILE_INTERNAL_INFORMATION);
1054
1055         ntStatus = STATUS_SUCCESS;
1056     }
1057
1058     return ntStatus;
1059 }
1060
1061 NTSTATUS
1062 AFSQueryEaInfo( IN PIRP Irp,
1063                 IN AFSDirectoryCB *DirectoryCB,
1064                 IN OUT PFILE_EA_INFORMATION Buffer,
1065                 IN OUT PLONG Length)
1066 {
1067
1068     UNREFERENCED_PARAMETER(Irp);
1069     UNREFERENCED_PARAMETER(DirectoryCB);
1070     NTSTATUS ntStatus = STATUS_INFO_LENGTH_MISMATCH;
1071
1072     RtlZeroMemory( Buffer,
1073                    *Length);
1074
1075     if( *Length >= sizeof( FILE_EA_INFORMATION))
1076     {
1077
1078         Buffer->EaSize = 0;
1079
1080         *Length -= sizeof( FILE_EA_INFORMATION);
1081
1082         ntStatus = STATUS_SUCCESS;
1083     }
1084
1085     return ntStatus;
1086 }
1087
1088 NTSTATUS
1089 AFSQueryPositionInfo( IN PIRP Irp,
1090                       IN AFSFcb *Fcb,
1091                       IN OUT PFILE_POSITION_INFORMATION Buffer,
1092                       IN OUT PLONG Length)
1093 {
1094
1095     UNREFERENCED_PARAMETER(Fcb);
1096     NTSTATUS ntStatus = STATUS_INFO_LENGTH_MISMATCH;
1097     PIO_STACK_LOCATION pIrpSp = IoGetCurrentIrpStackLocation( Irp);
1098
1099     if( *Length >= sizeof( FILE_POSITION_INFORMATION))
1100     {
1101
1102         RtlZeroMemory( Buffer,
1103                        *Length);
1104
1105         Buffer->CurrentByteOffset.QuadPart = pIrpSp->FileObject->CurrentByteOffset.QuadPart;
1106
1107         *Length -= sizeof( FILE_POSITION_INFORMATION);
1108
1109         ntStatus = STATUS_SUCCESS;
1110     }
1111
1112     return ntStatus;
1113 }
1114
1115 NTSTATUS
1116 AFSQueryNameInfo( IN PIRP Irp,
1117                   IN AFSDirectoryCB *DirectoryCB,
1118                   IN OUT PFILE_NAME_INFORMATION Buffer,
1119                   IN OUT PLONG Length)
1120 {
1121
1122     UNREFERENCED_PARAMETER(DirectoryCB);
1123     NTSTATUS ntStatus = STATUS_INFO_LENGTH_MISMATCH;
1124     ULONG ulCopyLength = 0;
1125     ULONG cchCopied = 0;
1126     AFSFcb *pFcb = NULL;
1127     AFSCcb *pCcb = NULL;
1128     IO_STACK_LOCATION *pIrpSp = IoGetCurrentIrpStackLocation( Irp);
1129     BOOLEAN bAddLeadingSlash = FALSE;
1130     BOOLEAN bAddTrailingSlash = FALSE;
1131     USHORT usFullNameLength = 0;
1132
1133     pFcb = (AFSFcb *)pIrpSp->FileObject->FsContext;
1134
1135     pCcb = (AFSCcb *)pIrpSp->FileObject->FsContext2;
1136
1137     if( *Length >= FIELD_OFFSET( FILE_NAME_INFORMATION, FileName))
1138     {
1139
1140         RtlZeroMemory( Buffer,
1141                        *Length);
1142
1143         if( pCcb->FullFileName.Length == 0 ||
1144             pCcb->FullFileName.Buffer[ 0] != L'\\')
1145         {
1146             bAddLeadingSlash = TRUE;
1147         }
1148
1149         if( pFcb->ObjectInformation->FileType == AFS_FILE_TYPE_DIRECTORY &&
1150             pCcb->FullFileName.Length > 0 &&
1151             pCcb->FullFileName.Buffer[ (pCcb->FullFileName.Length/sizeof( WCHAR)) - 1] != L'\\')
1152         {
1153             bAddTrailingSlash = TRUE;
1154         }
1155
1156         usFullNameLength = sizeof( WCHAR) +
1157                                     AFSServerName.Length +
1158                                     pCcb->FullFileName.Length;
1159
1160         if( bAddLeadingSlash)
1161         {
1162             usFullNameLength += sizeof( WCHAR);
1163         }
1164
1165         if( bAddTrailingSlash)
1166         {
1167             usFullNameLength += sizeof( WCHAR);
1168         }
1169
1170         if( *Length >= (LONG)(FIELD_OFFSET( FILE_NAME_INFORMATION, FileName) + (LONG)usFullNameLength))
1171         {
1172
1173             ulCopyLength = (LONG)usFullNameLength;
1174
1175             ntStatus = STATUS_SUCCESS;
1176         }
1177         else
1178         {
1179
1180             ulCopyLength = *Length - FIELD_OFFSET( FILE_NAME_INFORMATION, FileName);
1181
1182             ntStatus = STATUS_BUFFER_OVERFLOW;
1183         }
1184
1185         Buffer->FileNameLength = (ULONG)usFullNameLength;
1186
1187         *Length -= FIELD_OFFSET( FILE_NAME_INFORMATION, FileName);
1188
1189         if( ulCopyLength > 0)
1190         {
1191
1192             Buffer->FileName[ 0] = L'\\';
1193             ulCopyLength -= sizeof( WCHAR);
1194
1195             *Length -= sizeof( WCHAR);
1196             cchCopied += 1;
1197
1198             if( ulCopyLength >= AFSServerName.Length)
1199             {
1200
1201                 RtlCopyMemory( &Buffer->FileName[ 1],
1202                                AFSServerName.Buffer,
1203                                AFSServerName.Length);
1204
1205                 ulCopyLength -= AFSServerName.Length;
1206                 *Length -= AFSServerName.Length;
1207                 cchCopied += AFSServerName.Length/sizeof( WCHAR);
1208
1209                 if ( ulCopyLength > 0 &&
1210                      bAddLeadingSlash)
1211                 {
1212
1213                     Buffer->FileName[ cchCopied] = L'\\';
1214
1215                     ulCopyLength -= sizeof( WCHAR);
1216                     *Length -= sizeof( WCHAR);
1217                     cchCopied++;
1218                 }
1219
1220                 if( ulCopyLength >= pCcb->FullFileName.Length)
1221                 {
1222
1223                     RtlCopyMemory( &Buffer->FileName[ cchCopied],
1224                                    pCcb->FullFileName.Buffer,
1225                                    pCcb->FullFileName.Length);
1226
1227                     ulCopyLength -= pCcb->FullFileName.Length;
1228                     *Length -= pCcb->FullFileName.Length;
1229                     cchCopied += pCcb->FullFileName.Length/sizeof( WCHAR);
1230
1231                     if( ulCopyLength > 0 &&
1232                         bAddTrailingSlash)
1233                     {
1234                         Buffer->FileName[ cchCopied] = L'\\';
1235
1236                         *Length -= sizeof( WCHAR);
1237                     }
1238                 }
1239                 else
1240                 {
1241
1242                     RtlCopyMemory( &Buffer->FileName[ cchCopied],
1243                                    pCcb->FullFileName.Buffer,
1244                                    ulCopyLength);
1245
1246                     *Length -= ulCopyLength;
1247                 }
1248             }
1249         }
1250     }
1251
1252     return ntStatus;
1253 }
1254
1255 NTSTATUS
1256 AFSQueryShortNameInfo( IN PIRP Irp,
1257                        IN AFSDirectoryCB *DirectoryCB,
1258                        IN OUT PFILE_NAME_INFORMATION Buffer,
1259                        IN OUT PLONG Length)
1260 {
1261
1262     UNREFERENCED_PARAMETER(Irp);
1263     NTSTATUS ntStatus = STATUS_INFO_LENGTH_MISMATCH;
1264     ULONG ulCopyLength = 0;
1265
1266     RtlZeroMemory( Buffer,
1267                    *Length);
1268
1269     if( DirectoryCB->NameInformation.ShortNameLength == 0)
1270     {
1271
1272         //
1273         // The short name IS the long name
1274         //
1275
1276         if( *Length >= (LONG)FIELD_OFFSET( FILE_NAME_INFORMATION, FileName))
1277         {
1278
1279             if( *Length >= (LONG)(FIELD_OFFSET( FILE_NAME_INFORMATION, FileName) + (LONG)DirectoryCB->NameInformation.FileName.Length))
1280             {
1281
1282                 ulCopyLength = (LONG)DirectoryCB->NameInformation.FileName.Length;
1283
1284                 ntStatus = STATUS_SUCCESS;
1285             }
1286             else
1287             {
1288
1289                 ulCopyLength = *Length - FIELD_OFFSET( FILE_NAME_INFORMATION, FileName);
1290
1291                 ntStatus = STATUS_BUFFER_OVERFLOW;
1292             }
1293
1294             Buffer->FileNameLength = DirectoryCB->NameInformation.FileName.Length;
1295
1296             *Length -= FIELD_OFFSET( FILE_NAME_INFORMATION, FileName);
1297
1298             if( ulCopyLength > 0)
1299             {
1300
1301                 RtlCopyMemory( Buffer->FileName,
1302                                DirectoryCB->NameInformation.FileName.Buffer,
1303                                ulCopyLength);
1304
1305                 *Length -= ulCopyLength;
1306             }
1307         }
1308     }
1309     else
1310     {
1311
1312         if( *Length >= (LONG)FIELD_OFFSET( FILE_NAME_INFORMATION, FileName))
1313         {
1314
1315             if( *Length >= (LONG)(FIELD_OFFSET( FILE_NAME_INFORMATION, FileName) + (LONG)DirectoryCB->NameInformation.FileName.Length))
1316             {
1317
1318                 ulCopyLength = (LONG)DirectoryCB->NameInformation.ShortNameLength;
1319
1320                 ntStatus = STATUS_SUCCESS;
1321             }
1322             else
1323             {
1324
1325                 ulCopyLength = *Length - FIELD_OFFSET( FILE_NAME_INFORMATION, FileName);
1326
1327                 ntStatus = STATUS_BUFFER_OVERFLOW;
1328             }
1329
1330             Buffer->FileNameLength = DirectoryCB->NameInformation.ShortNameLength;
1331
1332             *Length -= FIELD_OFFSET( FILE_NAME_INFORMATION, FileName);
1333
1334             if( ulCopyLength > 0)
1335             {
1336
1337                 RtlCopyMemory( Buffer->FileName,
1338                                DirectoryCB->NameInformation.ShortName,
1339                                Buffer->FileNameLength);
1340
1341                 *Length -= ulCopyLength;
1342             }
1343         }
1344     }
1345
1346     return ntStatus;
1347 }
1348
1349 NTSTATUS
1350 AFSQueryNetworkInfo( IN PIRP Irp,
1351                      IN AFSDirectoryCB *DirectoryCB,
1352                      IN OUT PFILE_NETWORK_OPEN_INFORMATION Buffer,
1353                      IN OUT PLONG Length)
1354 {
1355
1356     NTSTATUS ntStatus = STATUS_INFO_LENGTH_MISMATCH;
1357     AFSDeviceExt *pDeviceExt = (AFSDeviceExt *)AFSRDRDeviceObject->DeviceExtension;
1358     AFSFcb *pFcb = NULL;
1359     AFSCcb *pCcb = NULL;
1360     PIO_STACK_LOCATION pIrpSp = IoGetCurrentIrpStackLocation( Irp);
1361     AFSFileInfoCB stFileInfo;
1362     AFSDirectoryCB *pParentDirectoryCB = NULL;
1363     UNICODE_STRING uniParentPath;
1364     ULONG ulFileAttribs = 0;
1365
1366     RtlZeroMemory( Buffer,
1367                    *Length);
1368
1369     if( *Length >= sizeof( FILE_NETWORK_OPEN_INFORMATION))
1370     {
1371
1372         ulFileAttribs = DirectoryCB->ObjectInformation->FileAttributes;
1373
1374         pFcb = (AFSFcb *)pIrpSp->FileObject->FsContext;
1375         pCcb = (AFSCcb *)pIrpSp->FileObject->FsContext2;
1376
1377         if( DirectoryCB->ObjectInformation->FileType == AFS_FILE_TYPE_SYMLINK)
1378         {
1379
1380             pParentDirectoryCB = AFSGetParentEntry( pCcb->NameArray);
1381
1382             AFSRetrieveParentPath( &pCcb->FullFileName,
1383                                    &uniParentPath);
1384
1385             RtlZeroMemory( &stFileInfo,
1386                            sizeof( AFSFileInfoCB));
1387
1388             //
1389             // Can't hold the Fcb while evaluating the path, leads to lock inversion
1390             //
1391
1392             AFSReleaseResource( &pFcb->NPFcb->Resource);
1393
1394             //
1395             // Its a reparse point regardless of whether the file attributes
1396             // can be retrieved for the target.
1397             //
1398
1399             if ( ulFileAttribs == FILE_ATTRIBUTE_NORMAL)
1400             {
1401
1402                 ulFileAttribs = FILE_ATTRIBUTE_REPARSE_POINT;
1403             }
1404             else
1405             {
1406
1407                 ulFileAttribs |= FILE_ATTRIBUTE_REPARSE_POINT;
1408             }
1409
1410             if( NT_SUCCESS( AFSRetrieveFileAttributes( pParentDirectoryCB,
1411                                                        DirectoryCB,
1412                                                        &uniParentPath,
1413                                                        pCcb->NameArray,
1414                                                        &pCcb->AuthGroup,
1415                                                        &stFileInfo)))
1416             {
1417
1418                 if ( stFileInfo.FileAttributes & FILE_ATTRIBUTE_DIRECTORY)
1419                 {
1420
1421                     ulFileAttribs |= FILE_ATTRIBUTE_DIRECTORY;
1422                 }
1423             }
1424
1425             AFSAcquireShared( &pFcb->NPFcb->Resource,
1426                               TRUE);
1427         }
1428
1429         AFSDbgTrace(( AFS_SUBSYSTEM_FILE_PROCESSING,
1430                       AFS_TRACE_LEVEL_VERBOSE_2,
1431                       "AFSQueryNetworkInfo %wZ Type 0x%x Attrib 0x%x -> 0x%x\n",
1432                       &pCcb->DirectoryCB->NameInformation.FileName,
1433                       pFcb->ObjectInformation->FileType,
1434                       pFcb->ObjectInformation->FileAttributes,
1435                       ulFileAttribs));
1436
1437         Buffer->CreationTime.QuadPart = DirectoryCB->ObjectInformation->CreationTime.QuadPart;
1438         Buffer->LastAccessTime.QuadPart = DirectoryCB->ObjectInformation->LastAccessTime.QuadPart;
1439         Buffer->LastWriteTime.QuadPart = DirectoryCB->ObjectInformation->LastWriteTime.QuadPart;
1440         Buffer->ChangeTime.QuadPart = DirectoryCB->ObjectInformation->ChangeTime.QuadPart;
1441
1442         Buffer->AllocationSize.QuadPart = DirectoryCB->ObjectInformation->AllocationSize.QuadPart;
1443         Buffer->EndOfFile.QuadPart = DirectoryCB->ObjectInformation->EndOfFile.QuadPart;
1444
1445         Buffer->FileAttributes = ulFileAttribs;
1446
1447         if( DirectoryCB->NameInformation.FileName.Buffer[ 0] == L'.' &&
1448             BooleanFlagOn( pDeviceExt->DeviceFlags, AFS_DEVICE_FLAG_HIDE_DOT_NAMES))
1449         {
1450
1451             if ( Buffer->FileAttributes != FILE_ATTRIBUTE_NORMAL)
1452             {
1453
1454                 Buffer->FileAttributes |= FILE_ATTRIBUTE_HIDDEN;
1455             }
1456             else
1457             {
1458
1459                 Buffer->FileAttributes = FILE_ATTRIBUTE_HIDDEN;
1460             }
1461         }
1462
1463         *Length -= sizeof( FILE_NETWORK_OPEN_INFORMATION);
1464
1465         ntStatus = STATUS_SUCCESS;
1466     }
1467
1468     return ntStatus;
1469 }
1470
1471 NTSTATUS
1472 AFSQueryStreamInfo( IN PIRP Irp,
1473                     IN AFSDirectoryCB *DirectoryCB,
1474                     IN OUT FILE_STREAM_INFORMATION *Buffer,
1475                     IN OUT PLONG Length)
1476 {
1477
1478     UNREFERENCED_PARAMETER(Irp);
1479     NTSTATUS ntStatus = STATUS_INFO_LENGTH_MISMATCH;
1480     ULONG ulCopyLength = 0;
1481
1482     if( *Length >= FIELD_OFFSET( FILE_STREAM_INFORMATION, StreamName))
1483     {
1484
1485         RtlZeroMemory( Buffer,
1486                        *Length);
1487
1488         Buffer->NextEntryOffset = 0;
1489
1490
1491         if( !BooleanFlagOn( DirectoryCB->ObjectInformation->FileAttributes, FILE_ATTRIBUTE_DIRECTORY))
1492         {
1493
1494             if( *Length >= (LONG)(FIELD_OFFSET( FILE_STREAM_INFORMATION, StreamName) + 14))  // ::$DATA
1495             {
1496
1497                 ulCopyLength = 14;
1498
1499                 ntStatus = STATUS_SUCCESS;
1500             }
1501             else
1502             {
1503
1504                 ulCopyLength = *Length - FIELD_OFFSET( FILE_STREAM_INFORMATION, StreamName);
1505
1506                 ntStatus = STATUS_BUFFER_OVERFLOW;
1507             }
1508
1509             Buffer->StreamNameLength = 14; // ::$DATA
1510
1511             Buffer->StreamSize.QuadPart = DirectoryCB->ObjectInformation->EndOfFile.QuadPart;
1512
1513             Buffer->StreamAllocationSize.QuadPart = DirectoryCB->ObjectInformation->AllocationSize.QuadPart;
1514
1515             *Length -= FIELD_OFFSET( FILE_STREAM_INFORMATION, StreamName);
1516
1517             if( ulCopyLength > 0)
1518             {
1519
1520                 RtlCopyMemory( Buffer->StreamName,
1521                                L"::$DATA",
1522                                ulCopyLength);
1523
1524                 *Length -= ulCopyLength;
1525             }
1526         }
1527         else
1528         {
1529
1530             Buffer->StreamNameLength = 0;       // No stream for a directory
1531
1532             // The response size is zero
1533
1534             ntStatus = STATUS_SUCCESS;
1535         }
1536     }
1537
1538     return ntStatus;
1539 }
1540
1541 NTSTATUS
1542 AFSQueryAttribTagInfo( IN PIRP Irp,
1543                        IN AFSDirectoryCB *DirectoryCB,
1544                        IN OUT FILE_ATTRIBUTE_TAG_INFORMATION *Buffer,
1545                        IN OUT PLONG Length)
1546 {
1547
1548     NTSTATUS ntStatus = STATUS_INFO_LENGTH_MISMATCH;
1549     AFSDeviceExt *pDeviceExt = (AFSDeviceExt *)AFSRDRDeviceObject->DeviceExtension;
1550     AFSFcb *pFcb = NULL;
1551     AFSCcb *pCcb = NULL;
1552     PIO_STACK_LOCATION pIrpSp = IoGetCurrentIrpStackLocation( Irp);
1553     AFSFileInfoCB stFileInfo;
1554     AFSDirectoryCB *pParentDirectoryCB = NULL;
1555     UNICODE_STRING uniParentPath;
1556     ULONG ulFileAttribs = 0;
1557
1558     if( *Length >= sizeof( FILE_ATTRIBUTE_TAG_INFORMATION))
1559     {
1560
1561         RtlZeroMemory( Buffer,
1562                        *Length);
1563
1564         ulFileAttribs = DirectoryCB->ObjectInformation->FileAttributes;
1565
1566         pFcb = (AFSFcb *)pIrpSp->FileObject->FsContext;
1567         pCcb = (AFSCcb *)pIrpSp->FileObject->FsContext2;
1568
1569         if( DirectoryCB->ObjectInformation->FileType == AFS_FILE_TYPE_SYMLINK)
1570         {
1571
1572             pParentDirectoryCB = AFSGetParentEntry( pCcb->NameArray);
1573
1574             AFSRetrieveParentPath( &pCcb->FullFileName,
1575                                    &uniParentPath);
1576
1577             RtlZeroMemory( &stFileInfo,
1578                            sizeof( AFSFileInfoCB));
1579
1580             //
1581             // Can't hold the Fcb while evaluating the path, leads to lock inversion
1582             //
1583
1584             AFSReleaseResource( &pFcb->NPFcb->Resource);
1585
1586             //
1587             // Its a reparse point regardless of whether the file attributes
1588             // can be retrieved for the target.
1589             //
1590
1591             if ( ulFileAttribs == FILE_ATTRIBUTE_NORMAL)
1592             {
1593
1594                 ulFileAttribs = FILE_ATTRIBUTE_REPARSE_POINT;
1595             }
1596             else
1597             {
1598
1599                 ulFileAttribs |= FILE_ATTRIBUTE_REPARSE_POINT;
1600             }
1601
1602             if( NT_SUCCESS( AFSRetrieveFileAttributes( pParentDirectoryCB,
1603                                                        DirectoryCB,
1604                                                        &uniParentPath,
1605                                                        pCcb->NameArray,
1606                                                        &pCcb->AuthGroup,
1607                                                        &stFileInfo)))
1608             {
1609
1610                 if ( stFileInfo.FileAttributes & FILE_ATTRIBUTE_DIRECTORY)
1611                 {
1612
1613                     ulFileAttribs |= FILE_ATTRIBUTE_DIRECTORY;
1614                 }
1615             }
1616
1617             AFSAcquireShared( &pFcb->NPFcb->Resource,
1618                               TRUE);
1619         }
1620
1621         AFSDbgTrace(( AFS_SUBSYSTEM_FILE_PROCESSING,
1622                       AFS_TRACE_LEVEL_VERBOSE_2,
1623                       "AFSAttribTagInfo %wZ Type 0x%x Attrib 0x%x -> 0x%x\n",
1624                       &pCcb->DirectoryCB->NameInformation.FileName,
1625                       pFcb->ObjectInformation->FileType,
1626                       pFcb->ObjectInformation->FileAttributes,
1627                       ulFileAttribs));
1628
1629         Buffer->FileAttributes = ulFileAttribs;
1630
1631         if( DirectoryCB->NameInformation.FileName.Buffer[ 0] == L'.' &&
1632             BooleanFlagOn( pDeviceExt->DeviceFlags, AFS_DEVICE_FLAG_HIDE_DOT_NAMES))
1633         {
1634
1635             if ( Buffer->FileAttributes != FILE_ATTRIBUTE_NORMAL)
1636             {
1637
1638                 Buffer->FileAttributes |= FILE_ATTRIBUTE_HIDDEN;
1639             }
1640             else
1641             {
1642
1643                 Buffer->FileAttributes = FILE_ATTRIBUTE_HIDDEN;
1644             }
1645         }
1646
1647         if ( DirectoryCB->ObjectInformation->FileType == AFS_FILE_TYPE_MOUNTPOINT)
1648         {
1649
1650             Buffer->ReparseTag = IO_REPARSE_TAG_SURROGATE|IO_REPARSE_TAG_OPENAFS_DFS;
1651         }
1652         else if( BooleanFlagOn( DirectoryCB->ObjectInformation->FileAttributes, FILE_ATTRIBUTE_REPARSE_POINT))
1653         {
1654
1655             Buffer->ReparseTag = IO_REPARSE_TAG_SYMLINK;
1656         }
1657
1658         *Length -= sizeof( FILE_ATTRIBUTE_TAG_INFORMATION);
1659
1660         ntStatus = STATUS_SUCCESS;
1661     }
1662
1663     return ntStatus;
1664 }
1665
1666 NTSTATUS
1667 AFSQueryRemoteProtocolInfo( IN PIRP Irp,
1668                             IN AFSDirectoryCB *DirectoryCB,
1669                             IN OUT FILE_REMOTE_PROTOCOL_INFORMATION *Buffer,
1670                             IN OUT PLONG Length)
1671 {
1672
1673     UNREFERENCED_PARAMETER(Irp);
1674     UNREFERENCED_PARAMETER(DirectoryCB);
1675     NTSTATUS ntStatus = STATUS_INFO_LENGTH_MISMATCH;
1676
1677     if( *Length >= sizeof( FILE_REMOTE_PROTOCOL_INFORMATION))
1678     {
1679
1680         RtlZeroMemory( Buffer,
1681                        *Length);
1682
1683         Buffer->StructureVersion = 1;
1684
1685         Buffer->StructureSize = sizeof(FILE_REMOTE_PROTOCOL_INFORMATION);
1686
1687         Buffer->Protocol = WNNC_NET_OPENAFS;
1688
1689         Buffer->ProtocolMajorVersion = 3;
1690
1691         Buffer->ProtocolMinorVersion = 0;
1692
1693         Buffer->ProtocolRevision = 0;
1694
1695         *Length -= sizeof( FILE_REMOTE_PROTOCOL_INFORMATION);
1696
1697         ntStatus = STATUS_SUCCESS;
1698     }
1699
1700     return ntStatus;
1701 }
1702
1703 NTSTATUS
1704 AFSQueryPhysicalNameInfo( IN PIRP Irp,
1705                           IN AFSDirectoryCB *DirectoryCB,
1706                           IN OUT PFILE_NETWORK_PHYSICAL_NAME_INFORMATION Buffer,
1707                           IN OUT PLONG Length)
1708 {
1709
1710     UNREFERENCED_PARAMETER(DirectoryCB);
1711     NTSTATUS ntStatus = STATUS_INFO_LENGTH_MISMATCH;
1712     ULONG ulCopyLength = 0;
1713     ULONG cchCopied = 0;
1714     AFSFcb *pFcb = NULL;
1715     AFSCcb *pCcb = NULL;
1716     IO_STACK_LOCATION *pIrpSp = IoGetCurrentIrpStackLocation( Irp);
1717     BOOLEAN bAddLeadingSlash = FALSE;
1718     USHORT usFullNameLength = 0;
1719
1720     pFcb = (AFSFcb *)pIrpSp->FileObject->FsContext;
1721
1722     pCcb = (AFSCcb *)pIrpSp->FileObject->FsContext2;
1723
1724     if( *Length >= FIELD_OFFSET( FILE_NETWORK_PHYSICAL_NAME_INFORMATION, FileName))
1725     {
1726
1727         RtlZeroMemory( Buffer,
1728                        *Length);
1729
1730         if( pCcb->FullFileName.Length == 0 ||
1731             pCcb->FullFileName.Buffer[ 0] != L'\\')
1732         {
1733             bAddLeadingSlash = TRUE;
1734         }
1735
1736         usFullNameLength = pCcb->FullFileName.Length;
1737
1738         if( bAddLeadingSlash)
1739         {
1740             usFullNameLength += sizeof( WCHAR);
1741         }
1742
1743         if( *Length >= (LONG)(FIELD_OFFSET( FILE_NETWORK_PHYSICAL_NAME_INFORMATION, FileName) + (LONG)usFullNameLength))
1744         {
1745             ulCopyLength = (LONG)usFullNameLength;
1746
1747             ntStatus = STATUS_SUCCESS;
1748         }
1749         else
1750         {
1751
1752             ulCopyLength = *Length - FIELD_OFFSET( FILE_NETWORK_PHYSICAL_NAME_INFORMATION, FileName);
1753
1754             ntStatus = STATUS_BUFFER_OVERFLOW;
1755         }
1756
1757         Buffer->FileNameLength = (ULONG)usFullNameLength;
1758
1759         *Length -= FIELD_OFFSET( FILE_NETWORK_PHYSICAL_NAME_INFORMATION, FileName);
1760
1761         if( ulCopyLength > 0)
1762         {
1763
1764             if( bAddLeadingSlash)
1765             {
1766
1767                 Buffer->FileName[ cchCopied] = L'\\';
1768
1769                 ulCopyLength -= sizeof( WCHAR);
1770                 *Length -= sizeof( WCHAR);
1771                 cchCopied++;
1772             }
1773
1774             if( ulCopyLength >= pCcb->FullFileName.Length)
1775             {
1776
1777                 RtlCopyMemory( &Buffer->FileName[ cchCopied],
1778                                pCcb->FullFileName.Buffer,
1779                                pCcb->FullFileName.Length);
1780
1781                 ulCopyLength -= pCcb->FullFileName.Length;
1782                 *Length -= pCcb->FullFileName.Length;
1783                 cchCopied += pCcb->FullFileName.Length/sizeof( WCHAR);
1784             }
1785             else
1786             {
1787
1788                 RtlCopyMemory( &Buffer->FileName[ cchCopied],
1789                                pCcb->FullFileName.Buffer,
1790                                ulCopyLength);
1791
1792                 *Length -= ulCopyLength;
1793             }
1794         }
1795     }
1796
1797     return ntStatus;
1798 }
1799
1800 NTSTATUS
1801 AFSSetBasicInfo( IN PIRP Irp,
1802                  IN AFSDirectoryCB *DirectoryCB,
1803                  OUT BOOLEAN *bUpdateFileInfo)
1804 {
1805     NTSTATUS ntStatus = STATUS_SUCCESS;
1806     PFILE_BASIC_INFORMATION pBuffer;
1807     PIO_STACK_LOCATION pIrpSp = IoGetCurrentIrpStackLocation( Irp);
1808     ULONG ulNotifyFilter = 0;
1809     AFSCcb *pCcb = NULL;
1810
1811     __Enter
1812     {
1813
1814         pCcb = (AFSCcb *)pIrpSp->FileObject->FsContext2;
1815
1816         pBuffer = (PFILE_BASIC_INFORMATION)Irp->AssociatedIrp.SystemBuffer;
1817
1818         pCcb->FileUnwindInfo.FileAttributes = (ULONG)-1;
1819
1820         if( pBuffer->FileAttributes != (ULONGLONG)0)
1821         {
1822
1823             //
1824             // Make sure that the reparse point attribute is not modified.
1825             // Fail if the RP attribute is requested but it is not
1826             // already a RP.  Otherwise, ignore it.
1827             //
1828
1829             if ( !BooleanFlagOn( DirectoryCB->ObjectInformation->FileAttributes,
1830                                  FILE_ATTRIBUTE_REPARSE_POINT) &&
1831                  BooleanFlagOn( pBuffer->FileAttributes,
1832                                 FILE_ATTRIBUTE_REPARSE_POINT))
1833             {
1834
1835                 try_return( ntStatus = STATUS_INVALID_PARAMETER);
1836             }
1837
1838             //
1839             // Make sure that the directory attribute is not modified.
1840             // Fail if the D attribute is requested but it is not
1841             // already a directory.  Otherwise, ignore it.
1842             //
1843
1844             if ( !BooleanFlagOn( DirectoryCB->ObjectInformation->FileAttributes,
1845                                  FILE_ATTRIBUTE_DIRECTORY) &&
1846                  BooleanFlagOn( pBuffer->FileAttributes,
1847                                 FILE_ATTRIBUTE_DIRECTORY))
1848             {
1849
1850                 try_return( ntStatus = STATUS_INVALID_PARAMETER);
1851             }
1852
1853             //
1854             // Save the original value
1855             //
1856
1857             pCcb->FileUnwindInfo.FileAttributes = DirectoryCB->ObjectInformation->FileAttributes;
1858
1859             if( BooleanFlagOn( pBuffer->FileAttributes, FILE_ATTRIBUTE_READONLY))
1860             {
1861
1862                 //
1863                 // Set the readonly flag.
1864                 //
1865
1866                 if ( !BooleanFlagOn( DirectoryCB->ObjectInformation->FileAttributes,
1867                                      FILE_ATTRIBUTE_READONLY))
1868                 {
1869
1870                     if ( DirectoryCB->ObjectInformation->FileAttributes == FILE_ATTRIBUTE_NORMAL)
1871                     {
1872
1873                         DirectoryCB->ObjectInformation->FileAttributes = FILE_ATTRIBUTE_READONLY;
1874                     }
1875                     else
1876                     {
1877
1878                         DirectoryCB->ObjectInformation->FileAttributes |= FILE_ATTRIBUTE_READONLY;
1879                     }
1880
1881                     ulNotifyFilter |= FILE_NOTIFY_CHANGE_ATTRIBUTES;
1882
1883                     SetFlag( DirectoryCB->ObjectInformation->Fcb->Flags, AFS_FCB_FLAG_FILE_MODIFIED);
1884                 }
1885             }
1886             else
1887             {
1888                 //
1889                 // Reset the readonly flag.
1890                 //
1891
1892                 if ( BooleanFlagOn( DirectoryCB->ObjectInformation->FileAttributes,
1893                                     FILE_ATTRIBUTE_READONLY))
1894                 {
1895
1896                     DirectoryCB->ObjectInformation->FileAttributes &= ~FILE_ATTRIBUTE_READONLY;
1897
1898                     if ( DirectoryCB->ObjectInformation->FileAttributes == 0)
1899                     {
1900
1901                         DirectoryCB->ObjectInformation->FileAttributes = FILE_ATTRIBUTE_NORMAL;
1902                     }
1903
1904                     ulNotifyFilter |= FILE_NOTIFY_CHANGE_ATTRIBUTES;
1905
1906                     SetFlag( DirectoryCB->ObjectInformation->Fcb->Flags, AFS_FCB_FLAG_FILE_MODIFIED);
1907                 }
1908             }
1909         }
1910
1911         pCcb->FileUnwindInfo.CreationTime.QuadPart = (ULONGLONG)-1;
1912
1913         if( pBuffer->CreationTime.QuadPart != (ULONGLONG)-1 &&
1914             pBuffer->CreationTime.QuadPart != (ULONGLONG)0)
1915         {
1916
1917             pCcb->FileUnwindInfo.CreationTime.QuadPart = DirectoryCB->ObjectInformation->CreationTime.QuadPart;
1918
1919             DirectoryCB->ObjectInformation->CreationTime.QuadPart = pBuffer->CreationTime.QuadPart;
1920
1921             ulNotifyFilter |= FILE_NOTIFY_CHANGE_CREATION;
1922
1923             SetFlag( DirectoryCB->ObjectInformation->Fcb->Flags, AFS_FCB_FLAG_FILE_MODIFIED | AFS_FCB_FLAG_UPDATE_CREATE_TIME);
1924         }
1925
1926         pCcb->FileUnwindInfo.LastAccessTime.QuadPart = (ULONGLONG)-1;
1927
1928         if( pBuffer->LastAccessTime.QuadPart != (ULONGLONG)-1 &&
1929             pBuffer->LastAccessTime.QuadPart != (ULONGLONG)0)
1930         {
1931
1932             pCcb->FileUnwindInfo.LastAccessTime.QuadPart = DirectoryCB->ObjectInformation->LastAccessTime.QuadPart;
1933
1934             DirectoryCB->ObjectInformation->LastAccessTime.QuadPart = pBuffer->LastAccessTime.QuadPart;
1935
1936             ulNotifyFilter |= FILE_NOTIFY_CHANGE_LAST_ACCESS;
1937
1938             SetFlag( DirectoryCB->ObjectInformation->Fcb->Flags, AFS_FCB_FLAG_FILE_MODIFIED | AFS_FCB_FLAG_UPDATE_ACCESS_TIME);
1939         }
1940
1941         pCcb->FileUnwindInfo.LastWriteTime.QuadPart = (ULONGLONG)-1;
1942
1943         if( pBuffer->LastWriteTime.QuadPart != (ULONGLONG)-1 &&
1944             pBuffer->LastWriteTime.QuadPart != (ULONGLONG)0)
1945         {
1946
1947             pCcb->FileUnwindInfo.LastWriteTime.QuadPart = DirectoryCB->ObjectInformation->LastWriteTime.QuadPart;
1948
1949             DirectoryCB->ObjectInformation->LastWriteTime.QuadPart = pBuffer->LastWriteTime.QuadPart;
1950
1951             ulNotifyFilter |= FILE_NOTIFY_CHANGE_LAST_WRITE;
1952
1953             SetFlag( DirectoryCB->ObjectInformation->Fcb->Flags, AFS_FCB_FLAG_FILE_MODIFIED | AFS_FCB_FLAG_UPDATE_LAST_WRITE_TIME);
1954
1955             SetFlag( pCcb->Flags, CCB_FLAG_LAST_WRITE_TIME_SET);
1956
1957         } else if ( pBuffer->LastWriteTime.QuadPart == (ULONGLONG)-1) {
1958
1959             SetFlag( pCcb->Flags, CCB_FLAG_LAST_WRITE_TIME_SET);
1960         }
1961
1962         pCcb->FileUnwindInfo.ChangeTime.QuadPart = (ULONGLONG)-1;
1963
1964         if( pBuffer->ChangeTime.QuadPart != (ULONGLONG)-1 &&
1965             pBuffer->ChangeTime.QuadPart != (ULONGLONG)0)
1966         {
1967
1968             pCcb->FileUnwindInfo.ChangeTime.QuadPart = DirectoryCB->ObjectInformation->ChangeTime.QuadPart;
1969
1970             DirectoryCB->ObjectInformation->ChangeTime.QuadPart = pBuffer->ChangeTime.QuadPart;
1971
1972             ulNotifyFilter |= FILE_NOTIFY_CHANGE_LAST_ACCESS;
1973
1974             SetFlag( DirectoryCB->ObjectInformation->Fcb->Flags, AFS_FCB_FLAG_FILE_MODIFIED | AFS_FCB_FLAG_UPDATE_CHANGE_TIME);
1975         }
1976
1977         if( ulNotifyFilter > 0)
1978         {
1979
1980             *bUpdateFileInfo = TRUE;
1981
1982             if( BooleanFlagOn( DirectoryCB->ObjectInformation->Flags, AFS_OBJECT_FLAGS_PARENT_FID))
1983             {
1984
1985                 AFSObjectInfoCB * pParentObjectInfo = AFSFindObjectInfo( DirectoryCB->ObjectInformation->VolumeCB,
1986                                                                          &DirectoryCB->ObjectInformation->ParentFileId,
1987                                                                          TRUE);
1988
1989                 if ( pParentObjectInfo != NULL)
1990                 {
1991                     AFSFsRtlNotifyFullReportChange( pParentObjectInfo,
1992                                                     pCcb,
1993                                                     (ULONG)ulNotifyFilter,
1994                                                     (ULONG)FILE_ACTION_MODIFIED);
1995
1996                     AFSReleaseObjectInfo( &pParentObjectInfo);
1997                 }
1998             }
1999         }
2000
2001 try_exit:
2002
2003         NOTHING;
2004     }
2005
2006     return ntStatus;
2007 }
2008
2009 NTSTATUS
2010 AFSSetDispositionInfo( IN PIRP Irp,
2011                        IN AFSDirectoryCB *DirectoryCB)
2012 {
2013     NTSTATUS ntStatus = STATUS_SUCCESS;
2014     PFILE_DISPOSITION_INFORMATION pBuffer;
2015     PIO_STACK_LOCATION pIrpSp = IoGetCurrentIrpStackLocation( Irp);
2016     AFSFcb *pFcb = NULL;
2017     AFSCcb *pCcb = NULL;
2018
2019     __Enter
2020     {
2021
2022         pBuffer = (PFILE_DISPOSITION_INFORMATION)Irp->AssociatedIrp.SystemBuffer;
2023
2024         pFcb = (AFSFcb *)pIrpSp->FileObject->FsContext;
2025
2026         pCcb = (AFSCcb *)pIrpSp->FileObject->FsContext2;
2027
2028         //
2029         // Can't delete the root
2030         //
2031
2032         if( pFcb->Header.NodeTypeCode == AFS_ROOT_FCB)
2033         {
2034
2035             AFSDbgTrace(( AFS_SUBSYSTEM_FILE_PROCESSING,
2036                           AFS_TRACE_LEVEL_ERROR,
2037                           "AFSSetDispositionInfo Attempt to delete root entry\n"));
2038
2039             try_return( ntStatus = STATUS_CANNOT_DELETE);
2040         }
2041
2042         //
2043         // If the file is read only then do not allow the delete
2044         //
2045
2046         if( BooleanFlagOn( DirectoryCB->ObjectInformation->FileAttributes, FILE_ATTRIBUTE_READONLY))
2047         {
2048
2049             AFSDbgTrace(( AFS_SUBSYSTEM_FILE_PROCESSING,
2050                           AFS_TRACE_LEVEL_ERROR,
2051                           "AFSSetDispositionInfo Attempt to delete read only entry %wZ\n",
2052                           &DirectoryCB->NameInformation.FileName));
2053
2054             try_return( ntStatus = STATUS_CANNOT_DELETE);
2055         }
2056
2057         if( pBuffer->DeleteFile)
2058         {
2059
2060             //
2061             // Check if the caller can delete the file
2062             //
2063
2064             ntStatus = AFSNotifyDelete( DirectoryCB,
2065                                         &pCcb->AuthGroup,
2066                                         TRUE);
2067
2068             if( !NT_SUCCESS( ntStatus))
2069             {
2070
2071                 AFSDbgTrace(( AFS_SUBSYSTEM_FILE_PROCESSING,
2072                               AFS_TRACE_LEVEL_ERROR,
2073                               "AFSSetDispositionInfo Cannot delete entry %wZ Status %08lX\n",
2074                               &DirectoryCB->NameInformation.FileName,
2075                               ntStatus));
2076
2077                 try_return( ntStatus);
2078             }
2079
2080             if( pFcb->Header.NodeTypeCode == AFS_DIRECTORY_FCB)
2081             {
2082
2083                 //
2084                 // Reduce the Link count in the object information block
2085                 // to correspond with the deletion of the directory entry.
2086                 //
2087
2088                 pFcb->ObjectInformation->Links--;
2089
2090                 //
2091                 // Check if this is a directory that there are not currently other opens
2092                 //
2093
2094                 if( pFcb->ObjectInformation->Specific.Directory.ChildOpenHandleCount > 0)
2095                 {
2096
2097                     AFSDbgTrace(( AFS_SUBSYSTEM_FILE_PROCESSING,
2098                                   AFS_TRACE_LEVEL_ERROR,
2099                                   "AFSSetDispositionInfo Attempt to delete directory %wZ with open %u handles\n",
2100                                   &DirectoryCB->NameInformation.FileName,
2101                                   pFcb->ObjectInformation->Specific.Directory.ChildOpenHandleCount));
2102
2103                     try_return( ntStatus = STATUS_DIRECTORY_NOT_EMPTY);
2104                 }
2105
2106                 //
2107                 // Make sure the directory is enumerated before checking to see if it is empty.
2108                 //
2109
2110                 if( !BooleanFlagOn( pFcb->ObjectInformation->Flags, AFS_OBJECT_FLAGS_DIRECTORY_ENUMERATED))
2111                 {
2112
2113                     AFSAcquireExcl( pFcb->ObjectInformation->Specific.Directory.DirectoryNodeHdr.TreeLock,
2114                                     TRUE);
2115
2116                     if( !BooleanFlagOn( pFcb->ObjectInformation->Flags, AFS_OBJECT_FLAGS_DIRECTORY_ENUMERATED))
2117                     {
2118
2119                         AFSDbgTrace(( AFS_SUBSYSTEM_FILE_PROCESSING,
2120                                       AFS_TRACE_LEVEL_VERBOSE,
2121                                       "AFSSetDispositionInfo Enumerating parent FID %08lX-%08lX-%08lX-%08lX\n",
2122                                       pFcb->ObjectInformation->FileId.Cell,
2123                                       pFcb->ObjectInformation->FileId.Volume,
2124                                       pFcb->ObjectInformation->FileId.Vnode,
2125                                       pFcb->ObjectInformation->FileId.Unique));
2126
2127                         ntStatus = AFSEnumerateDirectory( &pCcb->AuthGroup,
2128                                                           pFcb->ObjectInformation,
2129                                                           TRUE);
2130
2131                         if( !NT_SUCCESS( ntStatus))
2132                         {
2133
2134                             AFSReleaseResource( pFcb->ObjectInformation->Specific.Directory.DirectoryNodeHdr.TreeLock);
2135
2136                             AFSDbgTrace(( AFS_SUBSYSTEM_FILE_PROCESSING,
2137                                           AFS_TRACE_LEVEL_ERROR,
2138                                           "AFSSetDispositionInfo Failed to enumerate parent FID %08lX-%08lX-%08lX-%08lX Status %08lX\n",
2139                                           pFcb->ObjectInformation->FileId.Cell,
2140                                           pFcb->ObjectInformation->FileId.Volume,
2141                                           pFcb->ObjectInformation->FileId.Vnode,
2142                                           pFcb->ObjectInformation->FileId.Unique,
2143                                           ntStatus));
2144
2145                             try_return( ntStatus);
2146                         }
2147                     }
2148
2149                     AFSReleaseResource( pFcb->ObjectInformation->Specific.Directory.DirectoryNodeHdr.TreeLock);
2150                 }
2151
2152                 if( !AFSIsDirectoryEmptyForDelete( pFcb))
2153                 {
2154
2155                     AFSDbgTrace(( AFS_SUBSYSTEM_FILE_PROCESSING,
2156                                   AFS_TRACE_LEVEL_ERROR,
2157                                   "AFSSetDispositionInfo Attempt to delete non-empty directory %wZ\n",
2158                                   &DirectoryCB->NameInformation.FileName));
2159
2160                     try_return( ntStatus = STATUS_DIRECTORY_NOT_EMPTY);
2161                 }
2162
2163                 AFSDbgTrace(( AFS_SUBSYSTEM_FILE_PROCESSING,
2164                               AFS_TRACE_LEVEL_VERBOSE,
2165                               "AFSSetDispositionInfo Setting PENDING_DELETE on DirEntry  %p Name %wZ\n",
2166                               DirectoryCB,
2167                               &DirectoryCB->NameInformation.FileName));
2168
2169                 SetFlag( pCcb->DirectoryCB->Flags, AFS_DIR_ENTRY_PENDING_DELETE);
2170             }
2171             else if( pFcb->Header.NodeTypeCode == AFS_FILE_FCB)
2172             {
2173                 BOOLEAN bMmFlushed;
2174
2175                 AFSDbgTrace(( AFS_SUBSYSTEM_LOCK_PROCESSING,
2176                               AFS_TRACE_LEVEL_VERBOSE,
2177                               "AFSSetDispositionInfo Acquiring Fcb lock %p EXCL %08lX\n",
2178                               &pFcb->NPFcb->Resource,
2179                               PsGetCurrentThread()));
2180
2181                 AFSAcquireExcl( &pFcb->NPFcb->Resource,
2182                                 TRUE);
2183
2184                 AFSDbgTrace(( AFS_SUBSYSTEM_LOCK_PROCESSING|AFS_SUBSYSTEM_SECTION_OBJECT,
2185                               AFS_TRACE_LEVEL_VERBOSE,
2186                               "AFSSetDispositionInfo Acquiring Fcb SectionObject lock %p EXCL %08lX\n",
2187                               &pFcb->NPFcb->SectionObjectResource,
2188                               PsGetCurrentThread()));
2189
2190                 AFSAcquireExcl( &pFcb->NPFcb->SectionObjectResource,
2191                                 TRUE);
2192
2193                 __try
2194                 {
2195
2196                     //
2197                     // Attempt to flush any outstanding data
2198                     //
2199
2200                     bMmFlushed = MmFlushImageSection( &pFcb->NPFcb->SectionObjectPointers,
2201                                                       MmFlushForDelete);
2202
2203                     if ( bMmFlushed)
2204                     {
2205
2206                         //
2207                         // Set PENDING_DELETE before CcPurgeCacheSection to avoid a
2208                         // deadlock with Trend Micro's Enterprise anti-virus product
2209                         // which attempts to open the file which is being deleted.
2210                         //
2211
2212                         AFSDbgTrace(( AFS_SUBSYSTEM_FILE_PROCESSING,
2213                                       AFS_TRACE_LEVEL_VERBOSE,
2214                                       "AFSSetDispositionInfo Setting PENDING_DELETE on DirEntry %p Name %wZ\n",
2215                                       DirectoryCB,
2216                                       &DirectoryCB->NameInformation.FileName));
2217
2218                         SetFlag( pCcb->DirectoryCB->Flags, AFS_DIR_ENTRY_PENDING_DELETE);
2219
2220                         //
2221                         // Purge the cache as well
2222                         //
2223
2224                         if( pFcb->NPFcb->SectionObjectPointers.DataSectionObject != NULL)
2225                         {
2226
2227                             if ( !CcPurgeCacheSection( &pFcb->NPFcb->SectionObjectPointers,
2228                                                        NULL,
2229                                                        0,
2230                                                        TRUE))
2231                             {
2232
2233                                 SetFlag( pFcb->Flags, AFS_FCB_FLAG_PURGE_ON_CLOSE);
2234                             }
2235                         }
2236                     }
2237                 }
2238                 __except( EXCEPTION_EXECUTE_HANDLER)
2239                 {
2240
2241                     bMmFlushed = FALSE;
2242
2243                     ntStatus = GetExceptionCode();
2244
2245                     AFSDbgTrace(( 0,
2246                                   0,
2247                                   "EXCEPTION - AFSSetDispositionInfo MmFlushImageSection failed FID %08lX-%08lX-%08lX-%08lX Status 0x%08lX\n",
2248                                   pFcb->ObjectInformation->FileId.Cell,
2249                                   pFcb->ObjectInformation->FileId.Volume,
2250                                   pFcb->ObjectInformation->FileId.Vnode,
2251                                   pFcb->ObjectInformation->FileId.Unique,
2252                                   ntStatus));
2253                 }
2254
2255                 AFSDbgTrace(( AFS_SUBSYSTEM_LOCK_PROCESSING|AFS_SUBSYSTEM_SECTION_OBJECT,
2256                               AFS_TRACE_LEVEL_VERBOSE,
2257                               "AFSSetDispositionInfo Releasing Fcb SectionObject lock %p EXCL %08lX\n",
2258                               &pFcb->NPFcb->SectionObjectResource,
2259                               PsGetCurrentThread()));
2260
2261                 AFSReleaseResource( &pFcb->NPFcb->SectionObjectResource);
2262
2263                 AFSDbgTrace(( AFS_SUBSYSTEM_LOCK_PROCESSING,
2264                               AFS_TRACE_LEVEL_VERBOSE,
2265                               "AFSSetDispositionInfo Releasing Fcb lock %p EXCL %08lX\n",
2266                               &pFcb->NPFcb->Resource,
2267                               PsGetCurrentThread()));
2268
2269                 AFSReleaseResource( &pFcb->NPFcb->Resource);
2270
2271                 if ( !bMmFlushed)
2272                 {
2273
2274                     AFSDbgTrace(( AFS_SUBSYSTEM_FILE_PROCESSING,
2275                                   AFS_TRACE_LEVEL_ERROR,
2276                                   "AFSSetDispositionInfo Failed to flush image section for delete Entry %wZ\n",
2277                                   &DirectoryCB->NameInformation.FileName));
2278
2279                     try_return( ntStatus = STATUS_CANNOT_DELETE);
2280                 }
2281             }
2282             else if( pFcb->Header.NodeTypeCode == AFS_SYMBOLIC_LINK_FCB ||
2283                      pFcb->Header.NodeTypeCode == AFS_MOUNT_POINT_FCB ||
2284                      pFcb->Header.NodeTypeCode == AFS_DFS_LINK_FCB ||
2285                      pFcb->Header.NodeTypeCode == AFS_INVALID_FCB)
2286             {
2287
2288                 AFSDbgTrace(( AFS_SUBSYSTEM_FILE_PROCESSING,
2289                               AFS_TRACE_LEVEL_VERBOSE,
2290                               "AFSSetDispositionInfo Setting PENDING_DELETE on DirEntry %p Name %wZ\n",
2291                               DirectoryCB,
2292                               &DirectoryCB->NameInformation.FileName));
2293
2294                 SetFlag( pCcb->DirectoryCB->Flags, AFS_DIR_ENTRY_PENDING_DELETE);
2295             }
2296         }
2297         else
2298         {
2299
2300             ClearFlag( pCcb->DirectoryCB->Flags, AFS_DIR_ENTRY_PENDING_DELETE);
2301         }
2302
2303         //
2304         // OK, should be good to go, set the flag in the file object
2305         //
2306
2307         pIrpSp->FileObject->DeletePending = pBuffer->DeleteFile;
2308
2309 try_exit:
2310
2311         NOTHING;
2312     }
2313
2314     return ntStatus;
2315 }
2316
2317 NTSTATUS
2318 AFSSetFileLinkInfo( IN PIRP Irp)
2319 {
2320
2321     NTSTATUS ntStatus = STATUS_SUCCESS;
2322     AFSDeviceExt *pDeviceExt = (AFSDeviceExt *)AFSRDRDeviceObject->DeviceExtension;
2323     PIO_STACK_LOCATION pIrpSp = IoGetCurrentIrpStackLocation( Irp);
2324     PFILE_LINK_INFORMATION pFileLinkInfo = NULL;
2325     PFILE_OBJECT pSrcFileObj = NULL;
2326     PFILE_OBJECT pTargetFileObj = pIrpSp->Parameters.SetFile.FileObject;
2327     AFSFcb *pSrcFcb = NULL, *pTargetDcb = NULL;
2328     AFSCcb *pSrcCcb = NULL, *pTargetDirCcb = NULL;
2329     AFSObjectInfoCB *pSrcObject = NULL;
2330     AFSObjectInfoCB *pSrcParentObject = NULL, *pTargetParentObject = NULL;
2331     UNICODE_STRING uniSourceName, uniTargetName;
2332     UNICODE_STRING uniFullTargetName, uniTargetParentName;
2333     BOOLEAN bCommonParent = FALSE;
2334     AFSDirectoryCB *pTargetDirEntry = NULL;
2335     AFSDirectoryCB *pNewTargetDirEntry = NULL;
2336     ULONG ulTargetCRC;
2337     BOOLEAN bTargetEntryExists = FALSE;
2338     LONG lCount;
2339     BOOLEAN bReleaseTargetDirLock = FALSE;
2340     ULONG ulNotificationAction = 0, ulNotifyFilter = 0;
2341
2342     __Enter
2343     {
2344
2345         pSrcFileObj = pIrpSp->FileObject;
2346
2347         pSrcFcb = (AFSFcb *)pSrcFileObj->FsContext;
2348         pSrcCcb = (AFSCcb *)pSrcFileObj->FsContext2;
2349
2350         pSrcObject = pSrcFcb->ObjectInformation;
2351
2352         if ( BooleanFlagOn( pSrcObject->Flags, AFS_OBJECT_FLAGS_PARENT_FID))
2353         {
2354
2355             pSrcParentObject = AFSFindObjectInfo( pSrcObject->VolumeCB,
2356                                                   &pSrcObject->ParentFileId,
2357                                                   TRUE);
2358         }
2359
2360         if( pSrcParentObject == NULL)
2361         {
2362
2363             AFSDbgTrace(( AFS_SUBSYSTEM_FILE_PROCESSING,
2364                           AFS_TRACE_LEVEL_ERROR,
2365                           "AFSSetFileLinkInfo Unable to resolve SrcParentObject (INVALID_PARAMETER)\n"));
2366
2367             ASSERT( FALSE);
2368
2369             try_return( ntStatus = STATUS_INVALID_PARAMETER);
2370         }
2371
2372         pFileLinkInfo = (PFILE_LINK_INFORMATION)Irp->AssociatedIrp.SystemBuffer;
2373
2374         //
2375         // Perform some basic checks to ensure FS integrity
2376         //
2377
2378         if( pSrcFcb->Header.NodeTypeCode != AFS_FILE_FCB)
2379         {
2380
2381             AFSDbgTrace(( AFS_SUBSYSTEM_FILE_PROCESSING,
2382                           AFS_TRACE_LEVEL_ERROR,
2383                           "AFSSetFileLinkInfo Attempt to non-file (INVALID_PARAMETER)\n"));
2384
2385             try_return( ntStatus = STATUS_INVALID_PARAMETER);
2386         }
2387
2388         if( pTargetFileObj == NULL)
2389         {
2390
2391             if ( pFileLinkInfo->RootDirectory)
2392             {
2393
2394                 //
2395                 // The target directory is provided by HANDLE
2396                 // RootDirectory is only set when the target directory is not the same
2397                 // as the source directory.
2398                 //
2399                 // AFS only supports hard links within a single directory.
2400                 //
2401                 // The IOManager should translate any Handle to a FileObject for us.
2402                 // However, the failure to receive a FileObject is treated as a fatal
2403                 // error.
2404                 //
2405
2406                 AFSDbgTrace(( AFS_SUBSYSTEM_FILE_PROCESSING,
2407                               AFS_TRACE_LEVEL_ERROR,
2408                               "AFSSetFileLinkInfo Attempt to link %wZ to alternate directory by handle INVALID_PARAMETER\n",
2409                               &pSrcCcb->DirectoryCB->NameInformation.FileName));
2410
2411                 try_return( ntStatus = STATUS_INVALID_PARAMETER);
2412             }
2413             else
2414             {
2415
2416                 uniFullTargetName.Length = (USHORT)pFileLinkInfo->FileNameLength;
2417
2418                 uniFullTargetName.Buffer = (PWSTR)&pFileLinkInfo->FileName;
2419
2420                 AFSRetrieveFinalComponent( &uniFullTargetName,
2421                                            &uniTargetName);
2422
2423                 AFSRetrieveParentPath( &uniFullTargetName,
2424                                        &uniTargetParentName);
2425
2426                 if ( uniTargetParentName.Length == 0)
2427                 {
2428
2429                     //
2430                     // This is a simple rename. Here the target directory is the same as the source parent directory
2431                     // and the name is retrieved from the system buffer information
2432                     //
2433
2434                     pTargetParentObject = pSrcParentObject;
2435                 }
2436                 else
2437                 {
2438                     //
2439                     // uniTargetParentName contains the directory the renamed object
2440                     // will be moved to.  Must obtain the TargetParentObject.
2441                     //
2442
2443                     AFSDbgTrace(( AFS_SUBSYSTEM_FILE_PROCESSING,
2444                                   AFS_TRACE_LEVEL_ERROR,
2445                                   "AFSSetFileLinkInfo Attempt to link  %wZ to alternate directory %wZ (NOT_SAME_DEVICE)\n",
2446                                   &pSrcCcb->DirectoryCB->NameInformation.FileName,
2447                                   &uniFullTargetName));
2448
2449                     try_return( ntStatus = STATUS_NOT_SAME_DEVICE);
2450                 }
2451             }
2452
2453             pTargetDcb = pTargetParentObject->Fcb;
2454         }
2455         else
2456         {
2457
2458             //
2459             // So here we have the target directory taken from the targetfile object
2460             //
2461
2462             pTargetDcb = (AFSFcb *)pTargetFileObj->FsContext;
2463
2464             pTargetDirCcb = (AFSCcb *)pTargetFileObj->FsContext2;
2465
2466             pTargetParentObject = (AFSObjectInfoCB *)pTargetDcb->ObjectInformation;
2467
2468             //
2469             // Grab the target name which we setup in the IRP_MJ_CREATE handler. By how we set this up
2470             // it is only the target component of the rename operation
2471             //
2472
2473             uniTargetName = *((PUNICODE_STRING)&pTargetFileObj->FileName);
2474         }
2475
2476         //
2477         // The quick check to see if they are self linking.
2478         // Do the names match? Only do this where the parent directories are
2479         // the same
2480         //
2481
2482         if( pTargetParentObject == pSrcParentObject)
2483         {
2484
2485             if( FsRtlAreNamesEqual( &uniTargetName,
2486                                     &uniSourceName,
2487                                     FALSE,
2488                                     NULL))
2489             {
2490                 try_return( ntStatus = STATUS_SUCCESS);
2491             }
2492
2493             bCommonParent = TRUE;
2494         }
2495         else
2496         {
2497
2498             //
2499             // We do not allow cross-volume hard links
2500             //
2501
2502             if( pTargetParentObject->VolumeCB != pSrcObject->VolumeCB)
2503             {
2504
2505                 AFSDbgTrace(( AFS_SUBSYSTEM_FILE_PROCESSING,
2506                               AFS_TRACE_LEVEL_ERROR,
2507                               "AFSSetFileLinkInfo Attempt to link to different volume %wZ\n",
2508                               &pSrcCcb->DirectoryCB->NameInformation.FileName));
2509
2510                 try_return( ntStatus = STATUS_NOT_SAME_DEVICE);
2511             }
2512         }
2513
2514         ulTargetCRC = AFSGenerateCRC( &uniTargetName,
2515                                       FALSE);
2516
2517         AFSAcquireExcl( pTargetParentObject->Specific.Directory.DirectoryNodeHdr.TreeLock,
2518                         TRUE);
2519
2520         bReleaseTargetDirLock = TRUE;
2521
2522         AFSLocateCaseSensitiveDirEntry( pTargetParentObject->Specific.Directory.DirectoryNodeHdr.CaseSensitiveTreeHead,
2523                                         ulTargetCRC,
2524                                         &pTargetDirEntry);
2525
2526         if( pTargetDirEntry == NULL)
2527         {
2528
2529             //
2530             // Missed so perform a case insensitive lookup
2531             //
2532
2533             ulTargetCRC = AFSGenerateCRC( &uniTargetName,
2534                                           TRUE);
2535
2536             AFSLocateCaseInsensitiveDirEntry( pTargetParentObject->Specific.Directory.DirectoryNodeHdr.CaseInsensitiveTreeHead,
2537                                               ulTargetCRC,
2538                                               &pTargetDirEntry);
2539         }
2540
2541         if ( !BooleanFlagOn( pDeviceExt->DeviceFlags, AFS_DEVICE_FLAG_DISABLE_SHORTNAMES) &&
2542              pTargetDirEntry == NULL && RtlIsNameLegalDOS8Dot3( &uniTargetName,
2543                                                                 NULL,
2544                                                                 NULL))
2545         {
2546             //
2547             // Try the short name
2548             //
2549             AFSLocateShortNameDirEntry( pTargetParentObject->Specific.Directory.ShortNameTree,
2550                                         ulTargetCRC,
2551                                         &pTargetDirEntry);
2552         }
2553
2554         //
2555         // Increment our ref count on the dir entry
2556         //
2557
2558         if( pTargetDirEntry != NULL)
2559         {
2560
2561             ASSERT( BooleanFlagOn( pTargetDirEntry->ObjectInformation->Flags, AFS_OBJECT_FLAGS_PARENT_FID) &&
2562                     AFSIsEqualFID( &pTargetParentObject->FileId, &pTargetDirEntry->ObjectInformation->ParentFileId));
2563
2564             lCount = InterlockedIncrement( &pTargetDirEntry->DirOpenReferenceCount);
2565
2566             AFSDbgTrace(( AFS_SUBSYSTEM_DIRENTRY_REF_COUNTING,
2567                           AFS_TRACE_LEVEL_VERBOSE,
2568                           "AFSSetFileLinkInfo Increment count on %wZ DE %p Ccb %p Cnt %d\n",
2569                           &pTargetDirEntry->NameInformation.FileName,
2570                           pTargetDirEntry,
2571                           pSrcCcb,
2572                           lCount));
2573
2574             ASSERT( lCount >= 0);
2575
2576             if( !pFileLinkInfo->ReplaceIfExists)
2577             {
2578
2579                 AFSDbgTrace(( AFS_SUBSYSTEM_FILE_PROCESSING,
2580                               AFS_TRACE_LEVEL_ERROR,
2581                               "AFSSetFileLinkInfo Attempt to link with target collision %wZ Target %wZ\n",
2582                               &pSrcCcb->DirectoryCB->NameInformation.FileName,
2583                               &pTargetDirEntry->NameInformation.FileName));
2584
2585                 try_return( ntStatus = STATUS_OBJECT_NAME_COLLISION);
2586             }
2587
2588             AFSDbgTrace(( AFS_SUBSYSTEM_FILE_PROCESSING | AFS_SUBSYSTEM_DIRENTRY_REF_COUNTING,
2589                           AFS_TRACE_LEVEL_ERROR,
2590                           "AFSSetFileLinkInfo Target %wZ exists DE %p Count %d, performing delete of target\n",
2591                           &pTargetDirEntry->NameInformation.FileName,
2592                           pTargetDirEntry,
2593                           lCount));
2594
2595             //
2596             // Pull the directory entry from the parent
2597             //
2598
2599             AFSRemoveDirNodeFromParent( pTargetParentObject,
2600                                         pTargetDirEntry,
2601                                         FALSE);
2602
2603             bTargetEntryExists = TRUE;
2604         }
2605         else
2606         {
2607             AFSDbgTrace(( AFS_SUBSYSTEM_FILE_PROCESSING,
2608                           AFS_TRACE_LEVEL_VERBOSE,
2609                           "AFSSetFileLinkInfo Target does NOT exist, normal linking\n"));
2610         }
2611
2612         //
2613         // OK, this is a simple rename. Issue the rename
2614         // request to the service.
2615         //
2616
2617         ntStatus = AFSNotifyHardLink( pSrcObject,
2618                                       &pSrcCcb->AuthGroup,
2619                                       pSrcParentObject,
2620                                       pTargetDcb->ObjectInformation,
2621                                       pSrcCcb->DirectoryCB,
2622                                       &uniTargetName,
2623                                       pFileLinkInfo->ReplaceIfExists,
2624                                       &pNewTargetDirEntry);
2625
2626         if( ntStatus != STATUS_REPARSE &&
2627             !NT_SUCCESS( ntStatus))
2628         {
2629
2630             AFSDbgTrace(( AFS_SUBSYSTEM_FILE_PROCESSING,
2631                           AFS_TRACE_LEVEL_ERROR,
2632                           "AFSSetFileLinkInfo Failed link of %wZ to target %wZ Status %08lX\n",
2633                           &pSrcCcb->DirectoryCB->NameInformation.FileName,
2634                           &uniTargetName,
2635                           ntStatus));
2636
2637             try_return( ntStatus);
2638         }
2639
2640         if ( ntStatus != STATUS_REPARSE)
2641         {
2642
2643             AFSInsertDirectoryNode( pTargetDcb->ObjectInformation,
2644                                     pNewTargetDirEntry,
2645                                     TRUE);
2646         }
2647
2648         //
2649         // Send notification for the target link file
2650         //
2651
2652         if( bTargetEntryExists || pNewTargetDirEntry)
2653         {
2654
2655             ulNotificationAction = FILE_ACTION_MODIFIED;
2656         }
2657         else
2658         {
2659
2660             ulNotificationAction = FILE_ACTION_ADDED;
2661         }
2662
2663         AFSFsRtlNotifyFullReportChange( pTargetParentObject,
2664                                         pSrcCcb,
2665                                         (ULONG)ulNotifyFilter,
2666                                         (ULONG)ulNotificationAction);
2667
2668       try_exit:
2669
2670         if( !NT_SUCCESS( ntStatus))
2671         {
2672
2673             if( bTargetEntryExists)
2674             {
2675
2676                 AFSInsertDirectoryNode( pTargetParentObject,
2677                                         pTargetDirEntry,
2678                                         FALSE);
2679             }
2680         }
2681
2682         if( pTargetDirEntry != NULL)
2683         {
2684
2685             //
2686             // Release DirOpenReferenceCount obtained above
2687             //
2688
2689             lCount = InterlockedDecrement( &pTargetDirEntry->DirOpenReferenceCount);
2690
2691             AFSDbgTrace(( AFS_SUBSYSTEM_DIRENTRY_REF_COUNTING,
2692                           AFS_TRACE_LEVEL_VERBOSE,
2693                           "AFSSetFileLinkInfo Decrement count on %wZ DE %p Ccb %p Cnt %d\n",
2694                           &pTargetDirEntry->NameInformation.FileName,
2695                           pTargetDirEntry,
2696                           pSrcCcb,
2697                           lCount));
2698
2699             ASSERT( lCount >= 0);
2700         }
2701
2702         if( pNewTargetDirEntry != NULL)
2703         {
2704
2705             //
2706             // Release DirOpenReferenceCount obtained from AFSNotifyHardLink
2707             //
2708
2709             lCount = InterlockedDecrement( &pNewTargetDirEntry->DirOpenReferenceCount);
2710
2711             AFSDbgTrace(( AFS_SUBSYSTEM_DIRENTRY_REF_COUNTING,
2712                           AFS_TRACE_LEVEL_VERBOSE,
2713                           "AFSSetFileLinkInfo Decrement count on %wZ DE %p Ccb %p Cnt %d\n",
2714                           &pNewTargetDirEntry->NameInformation.FileName,
2715                           pNewTargetDirEntry,
2716                           pSrcCcb,
2717                           lCount));
2718
2719             ASSERT( lCount >= 0);
2720         }
2721
2722         if( bReleaseTargetDirLock)
2723         {
2724
2725             AFSReleaseResource( pTargetParentObject->Specific.Directory.DirectoryNodeHdr.TreeLock);
2726         }
2727
2728         if ( pSrcParentObject != NULL)
2729         {
2730
2731             AFSReleaseObjectInfo( &pSrcParentObject);
2732         }
2733
2734         //
2735         // No need to release pTargetParentObject as it is either a copy of pSrcParentObject
2736         // or (AFSFcb *)pTargetFileObj->FsContext->ObjectInformation
2737         //
2738
2739         pTargetParentObject = NULL;
2740     }
2741
2742     return ntStatus;
2743 }
2744
2745 NTSTATUS
2746 AFSSetRenameInfo( IN PIRP Irp)
2747 {
2748
2749     NTSTATUS ntStatus = STATUS_SUCCESS;
2750     AFSDeviceExt *pDeviceExt = (AFSDeviceExt *)AFSRDRDeviceObject->DeviceExtension;
2751     PIO_STACK_LOCATION pIrpSp = IoGetCurrentIrpStackLocation( Irp);
2752     AFSFcb *pSrcFcb = NULL, *pTargetDcb = NULL, *pTargetFcb = NULL;
2753     AFSCcb *pSrcCcb = NULL, *pTargetDirCcb = NULL;
2754     PFILE_OBJECT pSrcFileObj = pIrpSp->FileObject;
2755     PFILE_OBJECT pTargetFileObj = pIrpSp->Parameters.SetFile.FileObject;
2756     PFILE_OBJECT pTargetParentFileObj = NULL;
2757     PFILE_RENAME_INFORMATION pRenameInfo = NULL;
2758     UNICODE_STRING uniTargetName, uniSourceName, uniTargetParentName;
2759     BOOLEAN bReplaceIfExists = FALSE;
2760     UNICODE_STRING uniShortName;
2761     AFSDirectoryCB *pTargetDirEntry = NULL;
2762     ULONG ulTargetCRC = 0;
2763     BOOLEAN bTargetEntryExists = FALSE;
2764     AFSObjectInfoCB *pSrcObject = NULL;
2765     AFSObjectInfoCB *pSrcParentObject = NULL, *pTargetParentObject = NULL;
2766     AFSFileID stNewFid;
2767     ULONG ulNotificationAction = 0, ulNotifyFilter = 0;
2768     UNICODE_STRING uniFullTargetName;
2769     BOOLEAN bCommonParent = FALSE;
2770     BOOLEAN bReleaseTargetDirLock = FALSE;
2771     BOOLEAN bReleaseSourceDirLock = FALSE;
2772     BOOLEAN bDereferenceTargetParentObject = FALSE;
2773     PERESOURCE  pSourceDirLock = NULL;
2774     LONG lCount;
2775
2776     __Enter
2777     {
2778
2779         bReplaceIfExists = pIrpSp->Parameters.SetFile.ReplaceIfExists;
2780
2781         pRenameInfo = (PFILE_RENAME_INFORMATION)Irp->AssociatedIrp.SystemBuffer;
2782
2783         pSrcFcb = (AFSFcb *)pSrcFileObj->FsContext;
2784         pSrcCcb = (AFSCcb *)pSrcFileObj->FsContext2;
2785
2786         pSrcObject = pSrcFcb->ObjectInformation;
2787
2788         if ( BooleanFlagOn( pSrcObject->Flags, AFS_OBJECT_FLAGS_PARENT_FID))
2789         {
2790
2791             pSrcParentObject = AFSFindObjectInfo( pSrcObject->VolumeCB,
2792                                                   &pSrcObject->ParentFileId,
2793                                                   TRUE);
2794         }
2795
2796         if( pSrcParentObject == NULL)
2797         {
2798
2799             AFSDbgTrace(( AFS_SUBSYSTEM_FILE_PROCESSING,
2800                           AFS_TRACE_LEVEL_ERROR,
2801                           "AFSSetRenameInfo Unable to resolve SrcParentObject (INVALID_PARAMETER)\n"));
2802
2803             ASSERT( FALSE);
2804
2805             try_return( ntStatus = STATUS_INVALID_PARAMETER);
2806         }
2807
2808         //
2809         // Perform some basic checks to ensure FS integrity
2810         //
2811
2812         if( pSrcFcb->Header.NodeTypeCode == AFS_ROOT_FCB)
2813         {
2814
2815             //
2816             // Can't rename the root directory
2817             //
2818
2819             AFSDbgTrace(( AFS_SUBSYSTEM_FILE_PROCESSING,
2820                           AFS_TRACE_LEVEL_ERROR,
2821                           "AFSSetRenameInfo Attempt to rename root entry\n"));
2822
2823             try_return( ntStatus = STATUS_INVALID_PARAMETER);
2824         }
2825
2826         if( pSrcFcb->Header.NodeTypeCode == AFS_DIRECTORY_FCB)
2827         {
2828
2829             //
2830             // If there are any open children then fail the rename
2831             //
2832
2833             if( pSrcObject->Specific.Directory.ChildOpenHandleCount > 0)
2834             {
2835
2836                 AFSDbgTrace(( AFS_SUBSYSTEM_FILE_PROCESSING,
2837                               AFS_TRACE_LEVEL_ERROR,
2838                               "AFSSetRenameInfo Attempt to rename directory with open children %wZ\n",
2839                               &pSrcCcb->DirectoryCB->NameInformation.FileName));
2840
2841                 try_return( ntStatus = STATUS_ACCESS_DENIED);
2842             }
2843         }
2844
2845
2846         //
2847         // Extract off the final component name from the Fcb
2848         //
2849
2850         uniSourceName.Length = (USHORT)pSrcCcb->DirectoryCB->NameInformation.FileName.Length;
2851         uniSourceName.MaximumLength = uniSourceName.Length;
2852
2853         uniSourceName.Buffer = pSrcCcb->DirectoryCB->NameInformation.FileName.Buffer;
2854
2855         //
2856         // Resolve the target fileobject
2857         //
2858
2859         if( pTargetFileObj == NULL)
2860         {
2861
2862             if ( pRenameInfo->RootDirectory)
2863             {
2864
2865                 AFSDbgTrace(( AFS_SUBSYSTEM_FILE_PROCESSING,
2866                               AFS_TRACE_LEVEL_ERROR,
2867                               "AFSSetRenameInfo Handle provided but no FileObject ntStatus INVALID_PARAMETER\n"));
2868
2869                 try_return( ntStatus = STATUS_INVALID_PARAMETER);
2870             }
2871             else
2872             {
2873
2874                 uniFullTargetName.Length = (USHORT)pRenameInfo->FileNameLength;
2875
2876                 uniFullTargetName.Buffer = (PWSTR)&pRenameInfo->FileName;
2877
2878                 AFSRetrieveFinalComponent( &uniFullTargetName,
2879                                            &uniTargetName);
2880
2881                 AFSRetrieveParentPath( &uniFullTargetName,
2882                                        &uniTargetParentName);
2883
2884                 if ( uniTargetParentName.Length == 0)
2885                 {
2886
2887                     //
2888                     // This is a simple rename. Here the target directory is the same as the source parent directory
2889                     // and the name is retrieved from the system buffer information
2890                     //
2891
2892                     pTargetParentObject = pSrcParentObject;
2893                 }
2894                 else
2895                 {
2896                     //
2897                     // uniTargetParentName contains the directory the renamed object
2898                     // will be moved to.  Must obtain the TargetParentObject.
2899                     //
2900
2901                     AFSDbgTrace(( AFS_SUBSYSTEM_FILE_PROCESSING,
2902                                   AFS_TRACE_LEVEL_ERROR,
2903                                   "AFSSetRenameInfo Attempt to move %wZ to %wZ -- not yet supported (NOT_SAME_DEVICE)\n",
2904                                   &pSrcCcb->DirectoryCB->NameInformation.FileName,
2905                                   &uniFullTargetName));
2906
2907                     try_return( ntStatus = STATUS_NOT_SAME_DEVICE);
2908                 }
2909             }
2910
2911             pTargetDcb = pTargetParentObject->Fcb;
2912         }
2913         else
2914         {
2915
2916             //
2917             // So here we have the target directory taken from the targetfile object
2918             //
2919
2920             pTargetDcb = (AFSFcb *)pTargetFileObj->FsContext;
2921
2922             pTargetDirCcb = (AFSCcb *)pTargetFileObj->FsContext2;
2923
2924             pTargetParentObject = (AFSObjectInfoCB *)pTargetDcb->ObjectInformation;
2925
2926             //
2927             // Grab the target name which we setup in the IRP_MJ_CREATE handler. By how we set this up
2928             // it is only the target component of the rename operation
2929             //
2930
2931             uniTargetName = *((PUNICODE_STRING)&pTargetFileObj->FileName);
2932         }
2933
2934         //
2935         // The quick check to see if they are not really performing a rename
2936         // Do the names match? Only do this where the parent directories are
2937         // the same
2938         //
2939
2940         if( pTargetParentObject == pSrcParentObject)
2941         {
2942
2943             if( FsRtlAreNamesEqual( &uniTargetName,
2944                                     &uniSourceName,
2945                                     FALSE,
2946                                     NULL))
2947             {
2948                 try_return( ntStatus = STATUS_SUCCESS);
2949             }
2950
2951             bCommonParent = TRUE;
2952         }
2953         else
2954         {
2955
2956             bCommonParent = FALSE;
2957         }
2958
2959         //
2960         // We do not allow cross-volume renames to occur
2961         //
2962
2963         if( pTargetParentObject->VolumeCB != pSrcObject->VolumeCB)
2964         {
2965
2966             AFSDbgTrace(( AFS_SUBSYSTEM_FILE_PROCESSING,
2967                           AFS_TRACE_LEVEL_ERROR,
2968                           "AFSSetRenameInfo Attempt to rename directory to different volume %wZ\n",
2969                           &pSrcCcb->DirectoryCB->NameInformation.FileName));
2970
2971             try_return( ntStatus = STATUS_NOT_SAME_DEVICE);
2972         }
2973
2974         ulTargetCRC = AFSGenerateCRC( &uniTargetName,
2975                                       FALSE);
2976
2977         AFSAcquireExcl( pTargetParentObject->Specific.Directory.DirectoryNodeHdr.TreeLock,
2978                         TRUE);
2979
2980         bReleaseTargetDirLock = TRUE;
2981
2982         if( pTargetParentObject != pSrcParentObject)
2983         {
2984             AFSAcquireExcl( pSrcParentObject->Specific.Directory.DirectoryNodeHdr.TreeLock,
2985                             TRUE);
2986
2987             bReleaseSourceDirLock = TRUE;
2988
2989             pSourceDirLock = pSrcParentObject->Specific.Directory.DirectoryNodeHdr.TreeLock;
2990         }
2991
2992         AFSLocateCaseSensitiveDirEntry( pTargetParentObject->Specific.Directory.DirectoryNodeHdr.CaseSensitiveTreeHead,
2993                                         ulTargetCRC,
2994                                         &pTargetDirEntry);
2995
2996         if( pTargetDirEntry == NULL)
2997         {
2998
2999             //
3000             // Missed so perform a case insensitive lookup
3001             //
3002
3003             ulTargetCRC = AFSGenerateCRC( &uniTargetName,
3004                                           TRUE);
3005
3006             AFSLocateCaseInsensitiveDirEntry( pTargetParentObject->Specific.Directory.DirectoryNodeHdr.CaseInsensitiveTreeHead,
3007                                               ulTargetCRC,
3008                                               &pTargetDirEntry);
3009         }
3010
3011         if ( !BooleanFlagOn( pDeviceExt->DeviceFlags, AFS_DEVICE_FLAG_DISABLE_SHORTNAMES) &&
3012              pTargetDirEntry == NULL && RtlIsNameLegalDOS8Dot3( &uniTargetName,
3013                                                                NULL,
3014                                                                NULL))
3015         {
3016             //
3017             // Try the short name
3018             //
3019             AFSLocateShortNameDirEntry( pTargetParentObject->Specific.Directory.ShortNameTree,
3020                                         ulTargetCRC,
3021                                         &pTargetDirEntry);
3022         }
3023
3024         //
3025         // Increment our ref count on the dir entry
3026         //
3027
3028         if( pTargetDirEntry != NULL)
3029         {
3030
3031             ASSERT( BooleanFlagOn( pTargetDirEntry->ObjectInformation->Flags, AFS_OBJECT_FLAGS_PARENT_FID) &&
3032                     AFSIsEqualFID( &pTargetParentObject->FileId, &pTargetDirEntry->ObjectInformation->ParentFileId));
3033
3034             lCount = InterlockedIncrement( &pTargetDirEntry->DirOpenReferenceCount);
3035
3036             AFSDbgTrace(( AFS_SUBSYSTEM_DIRENTRY_REF_COUNTING,
3037                           AFS_TRACE_LEVEL_VERBOSE,
3038                           "AFSSetRenameInfo Increment count on %wZ DE %p Ccb %p Cnt %d\n",
3039                           &pTargetDirEntry->NameInformation.FileName,
3040                           pTargetDirEntry,
3041                           pSrcCcb,
3042                           lCount));
3043
3044             ASSERT( lCount >= 0);
3045
3046             if( !bReplaceIfExists)
3047             {
3048
3049                 AFSDbgTrace(( AFS_SUBSYSTEM_FILE_PROCESSING,
3050                               AFS_TRACE_LEVEL_ERROR,
3051                               "AFSSetRenameInfo Attempt to rename directory with target collision %wZ Target %wZ\n",
3052                               &pSrcCcb->DirectoryCB->NameInformation.FileName,
3053                               &pTargetDirEntry->NameInformation.FileName));
3054
3055                 try_return( ntStatus = STATUS_OBJECT_NAME_COLLISION);
3056             }
3057
3058             AFSDbgTrace(( AFS_SUBSYSTEM_FILE_PROCESSING | AFS_SUBSYSTEM_DIRENTRY_REF_COUNTING,
3059                           AFS_TRACE_LEVEL_ERROR,
3060                           "AFSSetRenameInfo Target %wZ exists DE %p Count %d, performing delete of target\n",
3061                           &pTargetDirEntry->NameInformation.FileName,
3062                           pTargetDirEntry,
3063                           lCount));
3064
3065             //
3066             // Pull the directory entry from the parent
3067             //
3068
3069             AFSRemoveDirNodeFromParent( pTargetParentObject,
3070                                         pTargetDirEntry,
3071                                         FALSE);
3072
3073             bTargetEntryExists = TRUE;
3074         }
3075         else
3076         {
3077             AFSDbgTrace(( AFS_SUBSYSTEM_FILE_PROCESSING,
3078                           AFS_TRACE_LEVEL_VERBOSE,
3079                           "AFSSetRenameInfo Target does NOT exist, normal rename\n"));
3080         }
3081
3082         //
3083         // We need to remove the DirEntry from the parent node, update the index
3084         // and reinsert it into the parent tree. Note that for entries with the
3085         // same parent we do not pull the node from the enumeration list
3086         //
3087
3088         AFSRemoveDirNodeFromParent( pSrcParentObject,
3089                                     pSrcCcb->DirectoryCB,
3090                                     !bCommonParent);
3091
3092         //
3093         // OK, this is a simple rename. Issue the rename
3094         // request to the service.
3095         //
3096
3097         ntStatus = AFSNotifyRename( pSrcObject,
3098                                     &pSrcCcb->AuthGroup,
3099                                     pSrcParentObject,
3100                                     pTargetDcb->ObjectInformation,
3101                                     pSrcCcb->DirectoryCB,
3102                                     &uniTargetName,
3103                                     &stNewFid);
3104
3105         if( !NT_SUCCESS( ntStatus))
3106         {
3107
3108             //
3109             // Attempt to re-insert the directory entry
3110             //
3111
3112             AFSInsertDirectoryNode( pSrcParentObject,
3113                                     pSrcCcb->DirectoryCB,
3114                                     !bCommonParent);
3115
3116             AFSDbgTrace(( AFS_SUBSYSTEM_FILE_PROCESSING,
3117                           AFS_TRACE_LEVEL_ERROR,
3118                           "AFSSetRenameInfo Failed rename of %wZ to target %wZ Status %08lX\n",
3119                           &pSrcCcb->DirectoryCB->NameInformation.FileName,
3120                           &uniTargetName,
3121                           ntStatus));
3122
3123             try_return( ntStatus);
3124         }
3125
3126         //
3127         // Set the notification up for the source file
3128         //
3129
3130         if( pSrcParentObject == pTargetParentObject &&
3131             !bTargetEntryExists)
3132         {
3133
3134             ulNotificationAction = FILE_ACTION_RENAMED_OLD_NAME;
3135         }
3136         else
3137         {
3138
3139             ulNotificationAction = FILE_ACTION_REMOVED;
3140         }
3141
3142         if( pSrcObject->FileType == AFS_FILE_TYPE_DIRECTORY)
3143         {
3144
3145             ulNotifyFilter = FILE_NOTIFY_CHANGE_DIR_NAME;
3146         }
3147         else
3148         {
3149
3150             ulNotifyFilter = FILE_NOTIFY_CHANGE_FILE_NAME;
3151         }
3152
3153         AFSFsRtlNotifyFullReportChange( pSrcParentObject,
3154                                         pSrcCcb,
3155                                         (ULONG)ulNotifyFilter,
3156                                         (ULONG)ulNotificationAction);
3157
3158         //
3159         // Update the name in the dir entry.
3160         //
3161
3162         ntStatus = AFSUpdateDirEntryName( pSrcCcb->DirectoryCB,
3163                                           &uniTargetName);
3164
3165         if( !NT_SUCCESS( ntStatus))
3166         {
3167
3168             //
3169             // Attempt to re-insert the directory entry
3170             //
3171
3172             AFSInsertDirectoryNode( pSrcParentObject,
3173                                     pSrcCcb->DirectoryCB,
3174                                     !bCommonParent);
3175
3176             AFSDbgTrace(( AFS_SUBSYSTEM_FILE_PROCESSING,
3177                           AFS_TRACE_LEVEL_ERROR,
3178                           "AFSSetRenameInfo Failed update of dir entry %wZ to target %wZ Status %08lX\n",
3179                           &pSrcCcb->DirectoryCB->NameInformation.FileName,
3180                           &uniTargetName,
3181                           ntStatus));
3182
3183             try_return( ntStatus);
3184         }
3185
3186         //
3187         // Update the object information block, if needed
3188         //
3189
3190         if( !AFSIsEqualFID( &pSrcObject->FileId,
3191                             &stNewFid))
3192         {