Windows: FilePhysicalNameInfo query AFS prefix
[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     AFSFcb *pFcb = NULL;
1125     AFSCcb *pCcb = NULL;
1126     IO_STACK_LOCATION *pIrpSp = IoGetCurrentIrpStackLocation( Irp);
1127
1128     pFcb = (AFSFcb *)pIrpSp->FileObject->FsContext;
1129
1130     pCcb = (AFSCcb *)pIrpSp->FileObject->FsContext2;
1131
1132     if( *Length >= FIELD_OFFSET( FILE_NAME_INFORMATION, FileName))
1133     {
1134
1135         RtlZeroMemory( Buffer,
1136                        *Length);
1137
1138         *Length -= FIELD_OFFSET( FILE_NAME_INFORMATION, FileName);
1139
1140         ntStatus = AFSGetFullFileName( pFcb,
1141                                        pCcb,
1142                                        &Buffer->FileNameLength,
1143                                        Buffer->FileName,
1144                                        Length);
1145     }
1146
1147     return ntStatus;
1148 }
1149
1150 NTSTATUS
1151 AFSQueryShortNameInfo( IN PIRP Irp,
1152                        IN AFSDirectoryCB *DirectoryCB,
1153                        IN OUT PFILE_NAME_INFORMATION Buffer,
1154                        IN OUT PLONG Length)
1155 {
1156
1157     UNREFERENCED_PARAMETER(Irp);
1158     NTSTATUS ntStatus = STATUS_INFO_LENGTH_MISMATCH;
1159     ULONG ulCopyLength = 0;
1160
1161     RtlZeroMemory( Buffer,
1162                    *Length);
1163
1164     if( DirectoryCB->NameInformation.ShortNameLength == 0)
1165     {
1166
1167         //
1168         // The short name IS the long name
1169         //
1170
1171         if( *Length >= (LONG)FIELD_OFFSET( FILE_NAME_INFORMATION, FileName))
1172         {
1173
1174             if( *Length >= (LONG)(FIELD_OFFSET( FILE_NAME_INFORMATION, FileName) + (LONG)DirectoryCB->NameInformation.FileName.Length))
1175             {
1176
1177                 ulCopyLength = (LONG)DirectoryCB->NameInformation.FileName.Length;
1178
1179                 ntStatus = STATUS_SUCCESS;
1180             }
1181             else
1182             {
1183
1184                 ulCopyLength = *Length - FIELD_OFFSET( FILE_NAME_INFORMATION, FileName);
1185
1186                 ntStatus = STATUS_BUFFER_OVERFLOW;
1187             }
1188
1189             Buffer->FileNameLength = DirectoryCB->NameInformation.FileName.Length;
1190
1191             *Length -= FIELD_OFFSET( FILE_NAME_INFORMATION, FileName);
1192
1193             if( ulCopyLength > 0)
1194             {
1195
1196                 RtlCopyMemory( Buffer->FileName,
1197                                DirectoryCB->NameInformation.FileName.Buffer,
1198                                ulCopyLength);
1199
1200                 *Length -= ulCopyLength;
1201             }
1202         }
1203     }
1204     else
1205     {
1206
1207         if( *Length >= (LONG)FIELD_OFFSET( FILE_NAME_INFORMATION, FileName))
1208         {
1209
1210             if( *Length >= (LONG)(FIELD_OFFSET( FILE_NAME_INFORMATION, FileName) + (LONG)DirectoryCB->NameInformation.FileName.Length))
1211             {
1212
1213                 ulCopyLength = (LONG)DirectoryCB->NameInformation.ShortNameLength;
1214
1215                 ntStatus = STATUS_SUCCESS;
1216             }
1217             else
1218             {
1219
1220                 ulCopyLength = *Length - FIELD_OFFSET( FILE_NAME_INFORMATION, FileName);
1221
1222                 ntStatus = STATUS_BUFFER_OVERFLOW;
1223             }
1224
1225             Buffer->FileNameLength = DirectoryCB->NameInformation.ShortNameLength;
1226
1227             *Length -= FIELD_OFFSET( FILE_NAME_INFORMATION, FileName);
1228
1229             if( ulCopyLength > 0)
1230             {
1231
1232                 RtlCopyMemory( Buffer->FileName,
1233                                DirectoryCB->NameInformation.ShortName,
1234                                Buffer->FileNameLength);
1235
1236                 *Length -= ulCopyLength;
1237             }
1238         }
1239     }
1240
1241     return ntStatus;
1242 }
1243
1244 NTSTATUS
1245 AFSQueryNetworkInfo( IN PIRP Irp,
1246                      IN AFSDirectoryCB *DirectoryCB,
1247                      IN OUT PFILE_NETWORK_OPEN_INFORMATION Buffer,
1248                      IN OUT PLONG Length)
1249 {
1250
1251     NTSTATUS ntStatus = STATUS_INFO_LENGTH_MISMATCH;
1252     AFSDeviceExt *pDeviceExt = (AFSDeviceExt *)AFSRDRDeviceObject->DeviceExtension;
1253     AFSFcb *pFcb = NULL;
1254     AFSCcb *pCcb = NULL;
1255     PIO_STACK_LOCATION pIrpSp = IoGetCurrentIrpStackLocation( Irp);
1256     AFSFileInfoCB stFileInfo;
1257     AFSDirectoryCB *pParentDirectoryCB = NULL;
1258     UNICODE_STRING uniParentPath;
1259     ULONG ulFileAttribs = 0;
1260
1261     RtlZeroMemory( Buffer,
1262                    *Length);
1263
1264     if( *Length >= sizeof( FILE_NETWORK_OPEN_INFORMATION))
1265     {
1266
1267         ulFileAttribs = DirectoryCB->ObjectInformation->FileAttributes;
1268
1269         pFcb = (AFSFcb *)pIrpSp->FileObject->FsContext;
1270         pCcb = (AFSCcb *)pIrpSp->FileObject->FsContext2;
1271
1272         if( DirectoryCB->ObjectInformation->FileType == AFS_FILE_TYPE_SYMLINK)
1273         {
1274
1275             pParentDirectoryCB = AFSGetParentEntry( pCcb->NameArray);
1276
1277             AFSRetrieveParentPath( &pCcb->FullFileName,
1278                                    &uniParentPath);
1279
1280             RtlZeroMemory( &stFileInfo,
1281                            sizeof( AFSFileInfoCB));
1282
1283             //
1284             // Can't hold the Fcb while evaluating the path, leads to lock inversion
1285             //
1286
1287             AFSReleaseResource( &pFcb->NPFcb->Resource);
1288
1289             //
1290             // Its a reparse point regardless of whether the file attributes
1291             // can be retrieved for the target.
1292             //
1293
1294             if ( ulFileAttribs == FILE_ATTRIBUTE_NORMAL)
1295             {
1296
1297                 ulFileAttribs = FILE_ATTRIBUTE_REPARSE_POINT;
1298             }
1299             else
1300             {
1301
1302                 ulFileAttribs |= FILE_ATTRIBUTE_REPARSE_POINT;
1303             }
1304
1305             if( NT_SUCCESS( AFSRetrieveFileAttributes( pParentDirectoryCB,
1306                                                        DirectoryCB,
1307                                                        &uniParentPath,
1308                                                        pCcb->NameArray,
1309                                                        &pCcb->AuthGroup,
1310                                                        &stFileInfo)))
1311             {
1312
1313                 if ( stFileInfo.FileAttributes & FILE_ATTRIBUTE_DIRECTORY)
1314                 {
1315
1316                     ulFileAttribs |= FILE_ATTRIBUTE_DIRECTORY;
1317                 }
1318             }
1319
1320             AFSAcquireShared( &pFcb->NPFcb->Resource,
1321                               TRUE);
1322         }
1323
1324         AFSDbgTrace(( AFS_SUBSYSTEM_FILE_PROCESSING,
1325                       AFS_TRACE_LEVEL_VERBOSE_2,
1326                       "AFSQueryNetworkInfo %wZ Type 0x%x Attrib 0x%x -> 0x%x\n",
1327                       &pCcb->DirectoryCB->NameInformation.FileName,
1328                       pFcb->ObjectInformation->FileType,
1329                       pFcb->ObjectInformation->FileAttributes,
1330                       ulFileAttribs));
1331
1332         Buffer->CreationTime.QuadPart = DirectoryCB->ObjectInformation->CreationTime.QuadPart;
1333         Buffer->LastAccessTime.QuadPart = DirectoryCB->ObjectInformation->LastAccessTime.QuadPart;
1334         Buffer->LastWriteTime.QuadPart = DirectoryCB->ObjectInformation->LastWriteTime.QuadPart;
1335         Buffer->ChangeTime.QuadPart = DirectoryCB->ObjectInformation->ChangeTime.QuadPart;
1336
1337         Buffer->AllocationSize.QuadPart = DirectoryCB->ObjectInformation->AllocationSize.QuadPart;
1338         Buffer->EndOfFile.QuadPart = DirectoryCB->ObjectInformation->EndOfFile.QuadPart;
1339
1340         Buffer->FileAttributes = ulFileAttribs;
1341
1342         if( DirectoryCB->NameInformation.FileName.Buffer[ 0] == L'.' &&
1343             BooleanFlagOn( pDeviceExt->DeviceFlags, AFS_DEVICE_FLAG_HIDE_DOT_NAMES))
1344         {
1345
1346             if ( Buffer->FileAttributes != FILE_ATTRIBUTE_NORMAL)
1347             {
1348
1349                 Buffer->FileAttributes |= FILE_ATTRIBUTE_HIDDEN;
1350             }
1351             else
1352             {
1353
1354                 Buffer->FileAttributes = FILE_ATTRIBUTE_HIDDEN;
1355             }
1356         }
1357
1358         *Length -= sizeof( FILE_NETWORK_OPEN_INFORMATION);
1359
1360         ntStatus = STATUS_SUCCESS;
1361     }
1362
1363     return ntStatus;
1364 }
1365
1366 NTSTATUS
1367 AFSQueryStreamInfo( IN PIRP Irp,
1368                     IN AFSDirectoryCB *DirectoryCB,
1369                     IN OUT FILE_STREAM_INFORMATION *Buffer,
1370                     IN OUT PLONG Length)
1371 {
1372
1373     UNREFERENCED_PARAMETER(Irp);
1374     NTSTATUS ntStatus = STATUS_INFO_LENGTH_MISMATCH;
1375     ULONG ulCopyLength = 0;
1376
1377     if( *Length >= FIELD_OFFSET( FILE_STREAM_INFORMATION, StreamName))
1378     {
1379
1380         RtlZeroMemory( Buffer,
1381                        *Length);
1382
1383         Buffer->NextEntryOffset = 0;
1384
1385
1386         if( !BooleanFlagOn( DirectoryCB->ObjectInformation->FileAttributes, FILE_ATTRIBUTE_DIRECTORY))
1387         {
1388
1389             if( *Length >= (LONG)(FIELD_OFFSET( FILE_STREAM_INFORMATION, StreamName) + 14))  // ::$DATA
1390             {
1391
1392                 ulCopyLength = 14;
1393
1394                 ntStatus = STATUS_SUCCESS;
1395             }
1396             else
1397             {
1398
1399                 ulCopyLength = *Length - FIELD_OFFSET( FILE_STREAM_INFORMATION, StreamName);
1400
1401                 ntStatus = STATUS_BUFFER_OVERFLOW;
1402             }
1403
1404             Buffer->StreamNameLength = 14; // ::$DATA
1405
1406             Buffer->StreamSize.QuadPart = DirectoryCB->ObjectInformation->EndOfFile.QuadPart;
1407
1408             Buffer->StreamAllocationSize.QuadPart = DirectoryCB->ObjectInformation->AllocationSize.QuadPart;
1409
1410             *Length -= FIELD_OFFSET( FILE_STREAM_INFORMATION, StreamName);
1411
1412             if( ulCopyLength > 0)
1413             {
1414
1415                 RtlCopyMemory( Buffer->StreamName,
1416                                L"::$DATA",
1417                                ulCopyLength);
1418
1419                 *Length -= ulCopyLength;
1420             }
1421         }
1422         else
1423         {
1424
1425             Buffer->StreamNameLength = 0;       // No stream for a directory
1426
1427             // The response size is zero
1428
1429             ntStatus = STATUS_SUCCESS;
1430         }
1431     }
1432
1433     return ntStatus;
1434 }
1435
1436 NTSTATUS
1437 AFSQueryAttribTagInfo( IN PIRP Irp,
1438                        IN AFSDirectoryCB *DirectoryCB,
1439                        IN OUT FILE_ATTRIBUTE_TAG_INFORMATION *Buffer,
1440                        IN OUT PLONG Length)
1441 {
1442
1443     NTSTATUS ntStatus = STATUS_INFO_LENGTH_MISMATCH;
1444     AFSDeviceExt *pDeviceExt = (AFSDeviceExt *)AFSRDRDeviceObject->DeviceExtension;
1445     AFSFcb *pFcb = NULL;
1446     AFSCcb *pCcb = NULL;
1447     PIO_STACK_LOCATION pIrpSp = IoGetCurrentIrpStackLocation( Irp);
1448     AFSFileInfoCB stFileInfo;
1449     AFSDirectoryCB *pParentDirectoryCB = NULL;
1450     UNICODE_STRING uniParentPath;
1451     ULONG ulFileAttribs = 0;
1452
1453     if( *Length >= sizeof( FILE_ATTRIBUTE_TAG_INFORMATION))
1454     {
1455
1456         RtlZeroMemory( Buffer,
1457                        *Length);
1458
1459         ulFileAttribs = DirectoryCB->ObjectInformation->FileAttributes;
1460
1461         pFcb = (AFSFcb *)pIrpSp->FileObject->FsContext;
1462         pCcb = (AFSCcb *)pIrpSp->FileObject->FsContext2;
1463
1464         if( DirectoryCB->ObjectInformation->FileType == AFS_FILE_TYPE_SYMLINK)
1465         {
1466
1467             pParentDirectoryCB = AFSGetParentEntry( pCcb->NameArray);
1468
1469             AFSRetrieveParentPath( &pCcb->FullFileName,
1470                                    &uniParentPath);
1471
1472             RtlZeroMemory( &stFileInfo,
1473                            sizeof( AFSFileInfoCB));
1474
1475             //
1476             // Can't hold the Fcb while evaluating the path, leads to lock inversion
1477             //
1478
1479             AFSReleaseResource( &pFcb->NPFcb->Resource);
1480
1481             //
1482             // Its a reparse point regardless of whether the file attributes
1483             // can be retrieved for the target.
1484             //
1485
1486             if ( ulFileAttribs == FILE_ATTRIBUTE_NORMAL)
1487             {
1488
1489                 ulFileAttribs = FILE_ATTRIBUTE_REPARSE_POINT;
1490             }
1491             else
1492             {
1493
1494                 ulFileAttribs |= FILE_ATTRIBUTE_REPARSE_POINT;
1495             }
1496
1497             if( NT_SUCCESS( AFSRetrieveFileAttributes( pParentDirectoryCB,
1498                                                        DirectoryCB,
1499                                                        &uniParentPath,
1500                                                        pCcb->NameArray,
1501                                                        &pCcb->AuthGroup,
1502                                                        &stFileInfo)))
1503             {
1504
1505                 if ( stFileInfo.FileAttributes & FILE_ATTRIBUTE_DIRECTORY)
1506                 {
1507
1508                     ulFileAttribs |= FILE_ATTRIBUTE_DIRECTORY;
1509                 }
1510             }
1511
1512             AFSAcquireShared( &pFcb->NPFcb->Resource,
1513                               TRUE);
1514         }
1515
1516         AFSDbgTrace(( AFS_SUBSYSTEM_FILE_PROCESSING,
1517                       AFS_TRACE_LEVEL_VERBOSE_2,
1518                       "AFSAttribTagInfo %wZ Type 0x%x Attrib 0x%x -> 0x%x\n",
1519                       &pCcb->DirectoryCB->NameInformation.FileName,
1520                       pFcb->ObjectInformation->FileType,
1521                       pFcb->ObjectInformation->FileAttributes,
1522                       ulFileAttribs));
1523
1524         Buffer->FileAttributes = ulFileAttribs;
1525
1526         if( DirectoryCB->NameInformation.FileName.Buffer[ 0] == L'.' &&
1527             BooleanFlagOn( pDeviceExt->DeviceFlags, AFS_DEVICE_FLAG_HIDE_DOT_NAMES))
1528         {
1529
1530             if ( Buffer->FileAttributes != FILE_ATTRIBUTE_NORMAL)
1531             {
1532
1533                 Buffer->FileAttributes |= FILE_ATTRIBUTE_HIDDEN;
1534             }
1535             else
1536             {
1537
1538                 Buffer->FileAttributes = FILE_ATTRIBUTE_HIDDEN;
1539             }
1540         }
1541
1542         if ( DirectoryCB->ObjectInformation->FileType == AFS_FILE_TYPE_MOUNTPOINT)
1543         {
1544
1545             Buffer->ReparseTag = IO_REPARSE_TAG_SURROGATE|IO_REPARSE_TAG_OPENAFS_DFS;
1546         }
1547         else if( BooleanFlagOn( DirectoryCB->ObjectInformation->FileAttributes, FILE_ATTRIBUTE_REPARSE_POINT))
1548         {
1549
1550             Buffer->ReparseTag = IO_REPARSE_TAG_SYMLINK;
1551         }
1552
1553         *Length -= sizeof( FILE_ATTRIBUTE_TAG_INFORMATION);
1554
1555         ntStatus = STATUS_SUCCESS;
1556     }
1557
1558     return ntStatus;
1559 }
1560
1561 NTSTATUS
1562 AFSQueryRemoteProtocolInfo( IN PIRP Irp,
1563                             IN AFSDirectoryCB *DirectoryCB,
1564                             IN OUT FILE_REMOTE_PROTOCOL_INFORMATION *Buffer,
1565                             IN OUT PLONG Length)
1566 {
1567
1568     UNREFERENCED_PARAMETER(Irp);
1569     UNREFERENCED_PARAMETER(DirectoryCB);
1570     NTSTATUS ntStatus = STATUS_INFO_LENGTH_MISMATCH;
1571
1572     if( *Length >= sizeof( FILE_REMOTE_PROTOCOL_INFORMATION))
1573     {
1574
1575         RtlZeroMemory( Buffer,
1576                        *Length);
1577
1578         Buffer->StructureVersion = 1;
1579
1580         Buffer->StructureSize = sizeof(FILE_REMOTE_PROTOCOL_INFORMATION);
1581
1582         Buffer->Protocol = WNNC_NET_OPENAFS;
1583
1584         Buffer->ProtocolMajorVersion = 3;
1585
1586         Buffer->ProtocolMinorVersion = 0;
1587
1588         Buffer->ProtocolRevision = 0;
1589
1590         *Length -= sizeof( FILE_REMOTE_PROTOCOL_INFORMATION);
1591
1592         ntStatus = STATUS_SUCCESS;
1593     }
1594
1595     return ntStatus;
1596 }
1597
1598 NTSTATUS
1599 AFSQueryPhysicalNameInfo( IN PIRP Irp,
1600                           IN AFSDirectoryCB *DirectoryCB,
1601                           IN OUT PFILE_NETWORK_PHYSICAL_NAME_INFORMATION Buffer,
1602                           IN OUT PLONG Length)
1603 {
1604
1605     UNREFERENCED_PARAMETER(DirectoryCB);
1606     NTSTATUS ntStatus = STATUS_INFO_LENGTH_MISMATCH;
1607     AFSFcb *pFcb = NULL;
1608     AFSCcb *pCcb = NULL;
1609     IO_STACK_LOCATION *pIrpSp = IoGetCurrentIrpStackLocation( Irp);
1610
1611     pFcb = (AFSFcb *)pIrpSp->FileObject->FsContext;
1612
1613     pCcb = (AFSCcb *)pIrpSp->FileObject->FsContext2;
1614
1615     if( *Length >= FIELD_OFFSET( FILE_NETWORK_PHYSICAL_NAME_INFORMATION, FileName))
1616     {
1617
1618         RtlZeroMemory( Buffer,
1619                        *Length);
1620
1621         *Length -= FIELD_OFFSET( FILE_NETWORK_PHYSICAL_NAME_INFORMATION, FileName);
1622
1623         ntStatus = AFSGetFullFileName( pFcb,
1624                                        pCcb,
1625                                        &Buffer->FileNameLength,
1626                                        Buffer->FileName,
1627                                        Length);
1628     }
1629
1630     return ntStatus;
1631 }
1632
1633 NTSTATUS
1634 AFSSetBasicInfo( IN PIRP Irp,
1635                  IN AFSDirectoryCB *DirectoryCB,
1636                  OUT BOOLEAN *bUpdateFileInfo)
1637 {
1638     NTSTATUS ntStatus = STATUS_SUCCESS;
1639     PFILE_BASIC_INFORMATION pBuffer;
1640     PIO_STACK_LOCATION pIrpSp = IoGetCurrentIrpStackLocation( Irp);
1641     ULONG ulNotifyFilter = 0;
1642     AFSCcb *pCcb = NULL;
1643
1644     __Enter
1645     {
1646
1647         pCcb = (AFSCcb *)pIrpSp->FileObject->FsContext2;
1648
1649         pBuffer = (PFILE_BASIC_INFORMATION)Irp->AssociatedIrp.SystemBuffer;
1650
1651         pCcb->FileUnwindInfo.FileAttributes = (ULONG)-1;
1652
1653         if( pBuffer->FileAttributes != (ULONGLONG)0)
1654         {
1655
1656             //
1657             // Make sure that the reparse point attribute is not modified.
1658             // Fail if the RP attribute is requested but it is not
1659             // already a RP.  Otherwise, ignore it.
1660             //
1661
1662             if ( !BooleanFlagOn( DirectoryCB->ObjectInformation->FileAttributes,
1663                                  FILE_ATTRIBUTE_REPARSE_POINT) &&
1664                  BooleanFlagOn( pBuffer->FileAttributes,
1665                                 FILE_ATTRIBUTE_REPARSE_POINT))
1666             {
1667
1668                 try_return( ntStatus = STATUS_INVALID_PARAMETER);
1669             }
1670
1671             //
1672             // Make sure that the directory attribute is not modified.
1673             // Fail if the D attribute is requested but it is not
1674             // already a directory.  Otherwise, ignore it.
1675             //
1676
1677             if ( !BooleanFlagOn( DirectoryCB->ObjectInformation->FileAttributes,
1678                                  FILE_ATTRIBUTE_DIRECTORY) &&
1679                  BooleanFlagOn( pBuffer->FileAttributes,
1680                                 FILE_ATTRIBUTE_DIRECTORY))
1681             {
1682
1683                 try_return( ntStatus = STATUS_INVALID_PARAMETER);
1684             }
1685
1686             //
1687             // Save the original value
1688             //
1689
1690             pCcb->FileUnwindInfo.FileAttributes = DirectoryCB->ObjectInformation->FileAttributes;
1691
1692             if( BooleanFlagOn( pBuffer->FileAttributes, FILE_ATTRIBUTE_READONLY))
1693             {
1694
1695                 //
1696                 // Set the readonly flag.
1697                 //
1698
1699                 if ( !BooleanFlagOn( DirectoryCB->ObjectInformation->FileAttributes,
1700                                      FILE_ATTRIBUTE_READONLY))
1701                 {
1702
1703                     if ( DirectoryCB->ObjectInformation->FileAttributes == FILE_ATTRIBUTE_NORMAL)
1704                     {
1705
1706                         DirectoryCB->ObjectInformation->FileAttributes = FILE_ATTRIBUTE_READONLY;
1707                     }
1708                     else
1709                     {
1710
1711                         DirectoryCB->ObjectInformation->FileAttributes |= FILE_ATTRIBUTE_READONLY;
1712                     }
1713
1714                     ulNotifyFilter |= FILE_NOTIFY_CHANGE_ATTRIBUTES;
1715
1716                     SetFlag( DirectoryCB->ObjectInformation->Fcb->Flags, AFS_FCB_FLAG_FILE_MODIFIED);
1717                 }
1718             }
1719             else
1720             {
1721                 //
1722                 // Reset the readonly flag.
1723                 //
1724
1725                 if ( BooleanFlagOn( DirectoryCB->ObjectInformation->FileAttributes,
1726                                     FILE_ATTRIBUTE_READONLY))
1727                 {
1728
1729                     DirectoryCB->ObjectInformation->FileAttributes &= ~FILE_ATTRIBUTE_READONLY;
1730
1731                     if ( DirectoryCB->ObjectInformation->FileAttributes == 0)
1732                     {
1733
1734                         DirectoryCB->ObjectInformation->FileAttributes = FILE_ATTRIBUTE_NORMAL;
1735                     }
1736
1737                     ulNotifyFilter |= FILE_NOTIFY_CHANGE_ATTRIBUTES;
1738
1739                     SetFlag( DirectoryCB->ObjectInformation->Fcb->Flags, AFS_FCB_FLAG_FILE_MODIFIED);
1740                 }
1741             }
1742         }
1743
1744         pCcb->FileUnwindInfo.CreationTime.QuadPart = (ULONGLONG)-1;
1745
1746         if( pBuffer->CreationTime.QuadPart != (ULONGLONG)-1 &&
1747             pBuffer->CreationTime.QuadPart != (ULONGLONG)0)
1748         {
1749
1750             pCcb->FileUnwindInfo.CreationTime.QuadPart = DirectoryCB->ObjectInformation->CreationTime.QuadPart;
1751
1752             DirectoryCB->ObjectInformation->CreationTime.QuadPart = pBuffer->CreationTime.QuadPart;
1753
1754             ulNotifyFilter |= FILE_NOTIFY_CHANGE_CREATION;
1755
1756             SetFlag( DirectoryCB->ObjectInformation->Fcb->Flags, AFS_FCB_FLAG_FILE_MODIFIED | AFS_FCB_FLAG_UPDATE_CREATE_TIME);
1757         }
1758
1759         pCcb->FileUnwindInfo.LastAccessTime.QuadPart = (ULONGLONG)-1;
1760
1761         if( pBuffer->LastAccessTime.QuadPart != (ULONGLONG)-1 &&
1762             pBuffer->LastAccessTime.QuadPart != (ULONGLONG)0)
1763         {
1764
1765             pCcb->FileUnwindInfo.LastAccessTime.QuadPart = DirectoryCB->ObjectInformation->LastAccessTime.QuadPart;
1766
1767             DirectoryCB->ObjectInformation->LastAccessTime.QuadPart = pBuffer->LastAccessTime.QuadPart;
1768
1769             ulNotifyFilter |= FILE_NOTIFY_CHANGE_LAST_ACCESS;
1770
1771             SetFlag( DirectoryCB->ObjectInformation->Fcb->Flags, AFS_FCB_FLAG_FILE_MODIFIED | AFS_FCB_FLAG_UPDATE_ACCESS_TIME);
1772         }
1773
1774         pCcb->FileUnwindInfo.LastWriteTime.QuadPart = (ULONGLONG)-1;
1775
1776         if( pBuffer->LastWriteTime.QuadPart != (ULONGLONG)-1 &&
1777             pBuffer->LastWriteTime.QuadPart != (ULONGLONG)0)
1778         {
1779
1780             pCcb->FileUnwindInfo.LastWriteTime.QuadPart = DirectoryCB->ObjectInformation->LastWriteTime.QuadPart;
1781
1782             DirectoryCB->ObjectInformation->LastWriteTime.QuadPart = pBuffer->LastWriteTime.QuadPart;
1783
1784             ulNotifyFilter |= FILE_NOTIFY_CHANGE_LAST_WRITE;
1785
1786             SetFlag( DirectoryCB->ObjectInformation->Fcb->Flags, AFS_FCB_FLAG_FILE_MODIFIED | AFS_FCB_FLAG_UPDATE_LAST_WRITE_TIME);
1787
1788             SetFlag( pCcb->Flags, CCB_FLAG_LAST_WRITE_TIME_SET);
1789
1790         } else if ( pBuffer->LastWriteTime.QuadPart == (ULONGLONG)-1) {
1791
1792             SetFlag( pCcb->Flags, CCB_FLAG_LAST_WRITE_TIME_SET);
1793         }
1794
1795         pCcb->FileUnwindInfo.ChangeTime.QuadPart = (ULONGLONG)-1;
1796
1797         if( pBuffer->ChangeTime.QuadPart != (ULONGLONG)-1 &&
1798             pBuffer->ChangeTime.QuadPart != (ULONGLONG)0)
1799         {
1800
1801             pCcb->FileUnwindInfo.ChangeTime.QuadPart = DirectoryCB->ObjectInformation->ChangeTime.QuadPart;
1802
1803             DirectoryCB->ObjectInformation->ChangeTime.QuadPart = pBuffer->ChangeTime.QuadPart;
1804
1805             ulNotifyFilter |= FILE_NOTIFY_CHANGE_LAST_ACCESS;
1806
1807             SetFlag( DirectoryCB->ObjectInformation->Fcb->Flags, AFS_FCB_FLAG_FILE_MODIFIED | AFS_FCB_FLAG_UPDATE_CHANGE_TIME);
1808         }
1809
1810         if( ulNotifyFilter > 0)
1811         {
1812
1813             *bUpdateFileInfo = TRUE;
1814
1815             if( BooleanFlagOn( DirectoryCB->ObjectInformation->Flags, AFS_OBJECT_FLAGS_PARENT_FID))
1816             {
1817
1818                 AFSObjectInfoCB * pParentObjectInfo = AFSFindObjectInfo( DirectoryCB->ObjectInformation->VolumeCB,
1819                                                                          &DirectoryCB->ObjectInformation->ParentFileId,
1820                                                                          TRUE);
1821
1822                 if ( pParentObjectInfo != NULL)
1823                 {
1824                     AFSFsRtlNotifyFullReportChange( pParentObjectInfo,
1825                                                     pCcb,
1826                                                     (ULONG)ulNotifyFilter,
1827                                                     (ULONG)FILE_ACTION_MODIFIED);
1828
1829                     AFSReleaseObjectInfo( &pParentObjectInfo);
1830                 }
1831             }
1832         }
1833
1834 try_exit:
1835
1836         NOTHING;
1837     }
1838
1839     return ntStatus;
1840 }
1841
1842 NTSTATUS
1843 AFSSetDispositionInfo( IN PIRP Irp,
1844                        IN AFSDirectoryCB *DirectoryCB)
1845 {
1846     NTSTATUS ntStatus = STATUS_SUCCESS;
1847     PFILE_DISPOSITION_INFORMATION pBuffer;
1848     PIO_STACK_LOCATION pIrpSp = IoGetCurrentIrpStackLocation( Irp);
1849     AFSFcb *pFcb = NULL;
1850     AFSCcb *pCcb = NULL;
1851
1852     __Enter
1853     {
1854
1855         pBuffer = (PFILE_DISPOSITION_INFORMATION)Irp->AssociatedIrp.SystemBuffer;
1856
1857         pFcb = (AFSFcb *)pIrpSp->FileObject->FsContext;
1858
1859         pCcb = (AFSCcb *)pIrpSp->FileObject->FsContext2;
1860
1861         //
1862         // Can't delete the root
1863         //
1864
1865         if( pFcb->Header.NodeTypeCode == AFS_ROOT_FCB)
1866         {
1867
1868             AFSDbgTrace(( AFS_SUBSYSTEM_FILE_PROCESSING,
1869                           AFS_TRACE_LEVEL_ERROR,
1870                           "AFSSetDispositionInfo Attempt to delete root entry\n"));
1871
1872             try_return( ntStatus = STATUS_CANNOT_DELETE);
1873         }
1874
1875         //
1876         // If the file is read only then do not allow the delete
1877         //
1878
1879         if( BooleanFlagOn( DirectoryCB->ObjectInformation->FileAttributes, FILE_ATTRIBUTE_READONLY))
1880         {
1881
1882             AFSDbgTrace(( AFS_SUBSYSTEM_FILE_PROCESSING,
1883                           AFS_TRACE_LEVEL_ERROR,
1884                           "AFSSetDispositionInfo Attempt to delete read only entry %wZ\n",
1885                           &DirectoryCB->NameInformation.FileName));
1886
1887             try_return( ntStatus = STATUS_CANNOT_DELETE);
1888         }
1889
1890         if( pBuffer->DeleteFile)
1891         {
1892
1893             //
1894             // Check if the caller can delete the file
1895             //
1896
1897             ntStatus = AFSNotifyDelete( DirectoryCB,
1898                                         &pCcb->AuthGroup,
1899                                         TRUE);
1900
1901             if( !NT_SUCCESS( ntStatus))
1902             {
1903
1904                 AFSDbgTrace(( AFS_SUBSYSTEM_FILE_PROCESSING,
1905                               AFS_TRACE_LEVEL_ERROR,
1906                               "AFSSetDispositionInfo Cannot delete entry %wZ Status %08lX\n",
1907                               &DirectoryCB->NameInformation.FileName,
1908                               ntStatus));
1909
1910                 try_return( ntStatus);
1911             }
1912
1913             if( pFcb->Header.NodeTypeCode == AFS_DIRECTORY_FCB)
1914             {
1915
1916                 //
1917                 // Reduce the Link count in the object information block
1918                 // to correspond with the deletion of the directory entry.
1919                 //
1920
1921                 pFcb->ObjectInformation->Links--;
1922
1923                 //
1924                 // Check if this is a directory that there are not currently other opens
1925                 //
1926
1927                 if( pFcb->ObjectInformation->Specific.Directory.ChildOpenHandleCount > 0)
1928                 {
1929
1930                     AFSDbgTrace(( AFS_SUBSYSTEM_FILE_PROCESSING,
1931                                   AFS_TRACE_LEVEL_ERROR,
1932                                   "AFSSetDispositionInfo Attempt to delete directory %wZ with open %u handles\n",
1933                                   &DirectoryCB->NameInformation.FileName,
1934                                   pFcb->ObjectInformation->Specific.Directory.ChildOpenHandleCount));
1935
1936                     try_return( ntStatus = STATUS_DIRECTORY_NOT_EMPTY);
1937                 }
1938
1939                 //
1940                 // Make sure the directory is enumerated before checking to see if it is empty.
1941                 //
1942
1943                 if( !BooleanFlagOn( pFcb->ObjectInformation->Flags, AFS_OBJECT_FLAGS_DIRECTORY_ENUMERATED))
1944                 {
1945
1946                     AFSAcquireExcl( pFcb->ObjectInformation->Specific.Directory.DirectoryNodeHdr.TreeLock,
1947                                     TRUE);
1948
1949                     if( !BooleanFlagOn( pFcb->ObjectInformation->Flags, AFS_OBJECT_FLAGS_DIRECTORY_ENUMERATED))
1950                     {
1951
1952                         AFSDbgTrace(( AFS_SUBSYSTEM_FILE_PROCESSING,
1953                                       AFS_TRACE_LEVEL_VERBOSE,
1954                                       "AFSSetDispositionInfo Enumerating parent FID %08lX-%08lX-%08lX-%08lX\n",
1955                                       pFcb->ObjectInformation->FileId.Cell,
1956                                       pFcb->ObjectInformation->FileId.Volume,
1957                                       pFcb->ObjectInformation->FileId.Vnode,
1958                                       pFcb->ObjectInformation->FileId.Unique));
1959
1960                         ntStatus = AFSEnumerateDirectory( &pCcb->AuthGroup,
1961                                                           pFcb->ObjectInformation,
1962                                                           TRUE);
1963
1964                         if( !NT_SUCCESS( ntStatus))
1965                         {
1966
1967                             AFSReleaseResource( pFcb->ObjectInformation->Specific.Directory.DirectoryNodeHdr.TreeLock);
1968
1969                             AFSDbgTrace(( AFS_SUBSYSTEM_FILE_PROCESSING,
1970                                           AFS_TRACE_LEVEL_ERROR,
1971                                           "AFSSetDispositionInfo Failed to enumerate parent FID %08lX-%08lX-%08lX-%08lX Status %08lX\n",
1972                                           pFcb->ObjectInformation->FileId.Cell,
1973                                           pFcb->ObjectInformation->FileId.Volume,
1974                                           pFcb->ObjectInformation->FileId.Vnode,
1975                                           pFcb->ObjectInformation->FileId.Unique,
1976                                           ntStatus));
1977
1978                             try_return( ntStatus);
1979                         }
1980                     }
1981
1982                     AFSReleaseResource( pFcb->ObjectInformation->Specific.Directory.DirectoryNodeHdr.TreeLock);
1983                 }
1984
1985                 if( !AFSIsDirectoryEmptyForDelete( pFcb))
1986                 {
1987
1988                     AFSDbgTrace(( AFS_SUBSYSTEM_FILE_PROCESSING,
1989                                   AFS_TRACE_LEVEL_ERROR,
1990                                   "AFSSetDispositionInfo Attempt to delete non-empty directory %wZ\n",
1991                                   &DirectoryCB->NameInformation.FileName));
1992
1993                     try_return( ntStatus = STATUS_DIRECTORY_NOT_EMPTY);
1994                 }
1995
1996                 AFSDbgTrace(( AFS_SUBSYSTEM_FILE_PROCESSING,
1997                               AFS_TRACE_LEVEL_VERBOSE,
1998                               "AFSSetDispositionInfo Setting PENDING_DELETE on DirEntry  %p Name %wZ\n",
1999                               DirectoryCB,
2000                               &DirectoryCB->NameInformation.FileName));
2001
2002                 SetFlag( pCcb->DirectoryCB->Flags, AFS_DIR_ENTRY_PENDING_DELETE);
2003             }
2004             else if( pFcb->Header.NodeTypeCode == AFS_FILE_FCB)
2005             {
2006                 BOOLEAN bMmFlushed;
2007
2008                 AFSDbgTrace(( AFS_SUBSYSTEM_LOCK_PROCESSING,
2009                               AFS_TRACE_LEVEL_VERBOSE,
2010                               "AFSSetDispositionInfo Acquiring Fcb lock %p EXCL %08lX\n",
2011                               &pFcb->NPFcb->Resource,
2012                               PsGetCurrentThread()));
2013
2014                 AFSAcquireExcl( &pFcb->NPFcb->Resource,
2015                                 TRUE);
2016
2017                 AFSDbgTrace(( AFS_SUBSYSTEM_LOCK_PROCESSING|AFS_SUBSYSTEM_SECTION_OBJECT,
2018                               AFS_TRACE_LEVEL_VERBOSE,
2019                               "AFSSetDispositionInfo Acquiring Fcb SectionObject lock %p EXCL %08lX\n",
2020                               &pFcb->NPFcb->SectionObjectResource,
2021                               PsGetCurrentThread()));
2022
2023                 AFSAcquireExcl( &pFcb->NPFcb->SectionObjectResource,
2024                                 TRUE);
2025
2026                 __try
2027                 {
2028
2029                     //
2030                     // Attempt to flush any outstanding data
2031                     //
2032
2033                     bMmFlushed = MmFlushImageSection( &pFcb->NPFcb->SectionObjectPointers,
2034                                                       MmFlushForDelete);
2035
2036                     if ( bMmFlushed)
2037                     {
2038
2039                         //
2040                         // Set PENDING_DELETE before CcPurgeCacheSection to avoid a
2041                         // deadlock with Trend Micro's Enterprise anti-virus product
2042                         // which attempts to open the file which is being deleted.
2043                         //
2044
2045                         AFSDbgTrace(( AFS_SUBSYSTEM_FILE_PROCESSING,
2046                                       AFS_TRACE_LEVEL_VERBOSE,
2047                                       "AFSSetDispositionInfo Setting PENDING_DELETE on DirEntry %p Name %wZ\n",
2048                                       DirectoryCB,
2049                                       &DirectoryCB->NameInformation.FileName));
2050
2051                         SetFlag( pCcb->DirectoryCB->Flags, AFS_DIR_ENTRY_PENDING_DELETE);
2052
2053                         //
2054                         // Purge the cache as well
2055                         //
2056
2057                         if( pFcb->NPFcb->SectionObjectPointers.DataSectionObject != NULL)
2058                         {
2059
2060                             if ( !CcPurgeCacheSection( &pFcb->NPFcb->SectionObjectPointers,
2061                                                        NULL,
2062                                                        0,
2063                                                        TRUE))
2064                             {
2065
2066                                 SetFlag( pFcb->Flags, AFS_FCB_FLAG_PURGE_ON_CLOSE);
2067                             }
2068                         }
2069                     }
2070                 }
2071                 __except( EXCEPTION_EXECUTE_HANDLER)
2072                 {
2073
2074                     bMmFlushed = FALSE;
2075
2076                     ntStatus = GetExceptionCode();
2077
2078                     AFSDbgTrace(( 0,
2079                                   0,
2080                                   "EXCEPTION - AFSSetDispositionInfo MmFlushImageSection failed FID %08lX-%08lX-%08lX-%08lX Status 0x%08lX\n",
2081                                   pFcb->ObjectInformation->FileId.Cell,
2082                                   pFcb->ObjectInformation->FileId.Volume,
2083                                   pFcb->ObjectInformation->FileId.Vnode,
2084                                   pFcb->ObjectInformation->FileId.Unique,
2085                                   ntStatus));
2086                 }
2087
2088                 AFSDbgTrace(( AFS_SUBSYSTEM_LOCK_PROCESSING|AFS_SUBSYSTEM_SECTION_OBJECT,
2089                               AFS_TRACE_LEVEL_VERBOSE,
2090                               "AFSSetDispositionInfo Releasing Fcb SectionObject lock %p EXCL %08lX\n",
2091                               &pFcb->NPFcb->SectionObjectResource,
2092                               PsGetCurrentThread()));
2093
2094                 AFSReleaseResource( &pFcb->NPFcb->SectionObjectResource);
2095
2096                 AFSDbgTrace(( AFS_SUBSYSTEM_LOCK_PROCESSING,
2097                               AFS_TRACE_LEVEL_VERBOSE,
2098                               "AFSSetDispositionInfo Releasing Fcb lock %p EXCL %08lX\n",
2099                               &pFcb->NPFcb->Resource,
2100                               PsGetCurrentThread()));
2101
2102                 AFSReleaseResource( &pFcb->NPFcb->Resource);
2103
2104                 if ( !bMmFlushed)
2105                 {
2106
2107                     AFSDbgTrace(( AFS_SUBSYSTEM_FILE_PROCESSING,
2108                                   AFS_TRACE_LEVEL_ERROR,
2109                                   "AFSSetDispositionInfo Failed to flush image section for delete Entry %wZ\n",
2110                                   &DirectoryCB->NameInformation.FileName));
2111
2112                     try_return( ntStatus = STATUS_CANNOT_DELETE);
2113                 }
2114             }
2115             else if( pFcb->Header.NodeTypeCode == AFS_SYMBOLIC_LINK_FCB ||
2116                      pFcb->Header.NodeTypeCode == AFS_MOUNT_POINT_FCB ||
2117                      pFcb->Header.NodeTypeCode == AFS_DFS_LINK_FCB ||
2118                      pFcb->Header.NodeTypeCode == AFS_INVALID_FCB)
2119             {
2120
2121                 AFSDbgTrace(( AFS_SUBSYSTEM_FILE_PROCESSING,
2122                               AFS_TRACE_LEVEL_VERBOSE,
2123                               "AFSSetDispositionInfo Setting PENDING_DELETE on DirEntry %p Name %wZ\n",
2124                               DirectoryCB,
2125                               &DirectoryCB->NameInformation.FileName));
2126
2127                 SetFlag( pCcb->DirectoryCB->Flags, AFS_DIR_ENTRY_PENDING_DELETE);
2128             }
2129         }
2130         else
2131         {
2132
2133             ClearFlag( pCcb->DirectoryCB->Flags, AFS_DIR_ENTRY_PENDING_DELETE);
2134         }
2135
2136         //
2137         // OK, should be good to go, set the flag in the file object
2138         //
2139
2140         pIrpSp->FileObject->DeletePending = pBuffer->DeleteFile;
2141
2142 try_exit:
2143
2144         NOTHING;
2145     }
2146
2147     return ntStatus;
2148 }
2149
2150 NTSTATUS
2151 AFSSetFileLinkInfo( IN PIRP Irp)
2152 {
2153
2154     NTSTATUS ntStatus = STATUS_SUCCESS;
2155     AFSDeviceExt *pDeviceExt = (AFSDeviceExt *)AFSRDRDeviceObject->DeviceExtension;
2156     PIO_STACK_LOCATION pIrpSp = IoGetCurrentIrpStackLocation( Irp);
2157     PFILE_LINK_INFORMATION pFileLinkInfo = NULL;
2158     PFILE_OBJECT pSrcFileObj = NULL;
2159     PFILE_OBJECT pTargetFileObj = pIrpSp->Parameters.SetFile.FileObject;
2160     AFSFcb *pSrcFcb = NULL, *pTargetDcb = NULL;
2161     AFSCcb *pSrcCcb = NULL, *pTargetDirCcb = NULL;
2162     AFSObjectInfoCB *pSrcObject = NULL;
2163     AFSObjectInfoCB *pSrcParentObject = NULL, *pTargetParentObject = NULL;
2164     UNICODE_STRING uniSourceName, uniTargetName;
2165     UNICODE_STRING uniFullTargetName, uniTargetParentName;
2166     BOOLEAN bCommonParent = FALSE;
2167     AFSDirectoryCB *pTargetDirEntry = NULL;
2168     AFSDirectoryCB *pNewTargetDirEntry = NULL;
2169     ULONG ulTargetCRC;
2170     BOOLEAN bTargetEntryExists = FALSE;
2171     LONG lCount;
2172     BOOLEAN bReleaseTargetDirLock = FALSE;
2173     ULONG ulNotificationAction = 0, ulNotifyFilter = 0;
2174
2175     __Enter
2176     {
2177
2178         pSrcFileObj = pIrpSp->FileObject;
2179
2180         pSrcFcb = (AFSFcb *)pSrcFileObj->FsContext;
2181         pSrcCcb = (AFSCcb *)pSrcFileObj->FsContext2;
2182
2183         pSrcObject = pSrcFcb->ObjectInformation;
2184
2185         if ( BooleanFlagOn( pSrcObject->Flags, AFS_OBJECT_FLAGS_PARENT_FID))
2186         {
2187
2188             pSrcParentObject = AFSFindObjectInfo( pSrcObject->VolumeCB,
2189                                                   &pSrcObject->ParentFileId,
2190                                                   TRUE);
2191         }
2192
2193         if( pSrcParentObject == NULL)
2194         {
2195
2196             AFSDbgTrace(( AFS_SUBSYSTEM_FILE_PROCESSING,
2197                           AFS_TRACE_LEVEL_ERROR,
2198                           "AFSSetFileLinkInfo Unable to resolve SrcParentObject (INVALID_PARAMETER)\n"));
2199
2200             ASSERT( FALSE);
2201
2202             try_return( ntStatus = STATUS_INVALID_PARAMETER);
2203         }
2204
2205         pFileLinkInfo = (PFILE_LINK_INFORMATION)Irp->AssociatedIrp.SystemBuffer;
2206
2207         //
2208         // Perform some basic checks to ensure FS integrity
2209         //
2210
2211         if( pSrcFcb->Header.NodeTypeCode != AFS_FILE_FCB)
2212         {
2213
2214             AFSDbgTrace(( AFS_SUBSYSTEM_FILE_PROCESSING,
2215                           AFS_TRACE_LEVEL_ERROR,
2216                           "AFSSetFileLinkInfo Attempt to non-file (INVALID_PARAMETER)\n"));
2217
2218             try_return( ntStatus = STATUS_INVALID_PARAMETER);
2219         }
2220
2221         if( pTargetFileObj == NULL)
2222         {
2223
2224             if ( pFileLinkInfo->RootDirectory)
2225             {
2226
2227                 //
2228                 // The target directory is provided by HANDLE
2229                 // RootDirectory is only set when the target directory is not the same
2230                 // as the source directory.
2231                 //
2232                 // AFS only supports hard links within a single directory.
2233                 //
2234                 // The IOManager should translate any Handle to a FileObject for us.
2235                 // However, the failure to receive a FileObject is treated as a fatal
2236                 // error.
2237                 //
2238
2239                 AFSDbgTrace(( AFS_SUBSYSTEM_FILE_PROCESSING,
2240                               AFS_TRACE_LEVEL_ERROR,
2241                               "AFSSetFileLinkInfo Attempt to link %wZ to alternate directory by handle INVALID_PARAMETER\n",
2242                               &pSrcCcb->DirectoryCB->NameInformation.FileName));
2243
2244                 try_return( ntStatus = STATUS_INVALID_PARAMETER);
2245             }
2246             else
2247             {
2248
2249                 uniFullTargetName.Length = (USHORT)pFileLinkInfo->FileNameLength;
2250
2251                 uniFullTargetName.Buffer = (PWSTR)&pFileLinkInfo->FileName;
2252
2253                 AFSRetrieveFinalComponent( &uniFullTargetName,
2254                                            &uniTargetName);
2255
2256                 AFSRetrieveParentPath( &uniFullTargetName,
2257                                        &uniTargetParentName);
2258
2259                 if ( uniTargetParentName.Length == 0)
2260                 {
2261
2262                     //
2263                     // This is a simple rename. Here the target directory is the same as the source parent directory
2264                     // and the name is retrieved from the system buffer information
2265                     //
2266
2267                     pTargetParentObject = pSrcParentObject;
2268                 }
2269                 else
2270                 {
2271                     //
2272                     // uniTargetParentName contains the directory the renamed object
2273                     // will be moved to.  Must obtain the TargetParentObject.
2274                     //
2275
2276                     AFSDbgTrace(( AFS_SUBSYSTEM_FILE_PROCESSING,
2277                                   AFS_TRACE_LEVEL_ERROR,
2278                                   "AFSSetFileLinkInfo Attempt to link  %wZ to alternate directory %wZ (NOT_SAME_DEVICE)\n",
2279                                   &pSrcCcb->DirectoryCB->NameInformation.FileName,
2280                                   &uniFullTargetName));
2281
2282                     try_return( ntStatus = STATUS_NOT_SAME_DEVICE);
2283                 }
2284             }
2285
2286             pTargetDcb = pTargetParentObject->Fcb;
2287         }
2288         else
2289         {
2290
2291             //
2292             // So here we have the target directory taken from the targetfile object
2293             //
2294
2295             pTargetDcb = (AFSFcb *)pTargetFileObj->FsContext;
2296
2297             pTargetDirCcb = (AFSCcb *)pTargetFileObj->FsContext2;
2298
2299             pTargetParentObject = (AFSObjectInfoCB *)pTargetDcb->ObjectInformation;
2300
2301             //
2302             // Grab the target name which we setup in the IRP_MJ_CREATE handler. By how we set this up
2303             // it is only the target component of the rename operation
2304             //
2305
2306             uniTargetName = *((PUNICODE_STRING)&pTargetFileObj->FileName);
2307         }
2308
2309         //
2310         // The quick check to see if they are self linking.
2311         // Do the names match? Only do this where the parent directories are
2312         // the same
2313         //
2314
2315         if( pTargetParentObject == pSrcParentObject)
2316         {
2317
2318             if( FsRtlAreNamesEqual( &uniTargetName,
2319                                     &uniSourceName,
2320                                     FALSE,
2321                                     NULL))
2322             {
2323                 try_return( ntStatus = STATUS_SUCCESS);
2324             }
2325
2326             bCommonParent = TRUE;
2327         }
2328         else
2329         {
2330
2331             //
2332             // We do not allow cross-volume hard links
2333             //
2334
2335             if( pTargetParentObject->VolumeCB != pSrcObject->VolumeCB)
2336             {
2337
2338                 AFSDbgTrace(( AFS_SUBSYSTEM_FILE_PROCESSING,
2339                               AFS_TRACE_LEVEL_ERROR,
2340                               "AFSSetFileLinkInfo Attempt to link to different volume %wZ\n",
2341                               &pSrcCcb->DirectoryCB->NameInformation.FileName));
2342
2343                 try_return( ntStatus = STATUS_NOT_SAME_DEVICE);
2344             }
2345         }
2346
2347         ulTargetCRC = AFSGenerateCRC( &uniTargetName,
2348                                       FALSE);
2349
2350         AFSAcquireExcl( pTargetParentObject->Specific.Directory.DirectoryNodeHdr.TreeLock,
2351                         TRUE);
2352
2353         bReleaseTargetDirLock = TRUE;
2354
2355         AFSLocateCaseSensitiveDirEntry( pTargetParentObject->Specific.Directory.DirectoryNodeHdr.CaseSensitiveTreeHead,
2356                                         ulTargetCRC,
2357                                         &pTargetDirEntry);
2358
2359         if( pTargetDirEntry == NULL)
2360         {
2361
2362             //
2363             // Missed so perform a case insensitive lookup
2364             //
2365
2366             ulTargetCRC = AFSGenerateCRC( &uniTargetName,
2367                                           TRUE);
2368
2369             AFSLocateCaseInsensitiveDirEntry( pTargetParentObject->Specific.Directory.DirectoryNodeHdr.CaseInsensitiveTreeHead,
2370                                               ulTargetCRC,
2371                                               &pTargetDirEntry);
2372         }
2373
2374         if ( !BooleanFlagOn( pDeviceExt->DeviceFlags, AFS_DEVICE_FLAG_DISABLE_SHORTNAMES) &&
2375              pTargetDirEntry == NULL && RtlIsNameLegalDOS8Dot3( &uniTargetName,
2376                                                                 NULL,
2377                                                                 NULL))
2378         {
2379             //
2380             // Try the short name
2381             //
2382             AFSLocateShortNameDirEntry( pTargetParentObject->Specific.Directory.ShortNameTree,
2383                                         ulTargetCRC,
2384                                         &pTargetDirEntry);
2385         }
2386
2387         //
2388         // Increment our ref count on the dir entry
2389         //
2390
2391         if( pTargetDirEntry != NULL)
2392         {
2393
2394             ASSERT( BooleanFlagOn( pTargetDirEntry->ObjectInformation->Flags, AFS_OBJECT_FLAGS_PARENT_FID) &&
2395                     AFSIsEqualFID( &pTargetParentObject->FileId, &pTargetDirEntry->ObjectInformation->ParentFileId));
2396
2397             lCount = InterlockedIncrement( &pTargetDirEntry->DirOpenReferenceCount);
2398
2399             AFSDbgTrace(( AFS_SUBSYSTEM_DIRENTRY_REF_COUNTING,
2400                           AFS_TRACE_LEVEL_VERBOSE,
2401                           "AFSSetFileLinkInfo Increment count on %wZ DE %p Ccb %p Cnt %d\n",
2402                           &pTargetDirEntry->NameInformation.FileName,
2403                           pTargetDirEntry,
2404                           pSrcCcb,
2405                           lCount));
2406
2407             ASSERT( lCount >= 0);
2408
2409             if( !pFileLinkInfo->ReplaceIfExists)
2410             {
2411
2412                 AFSDbgTrace(( AFS_SUBSYSTEM_FILE_PROCESSING,
2413                               AFS_TRACE_LEVEL_ERROR,
2414                               "AFSSetFileLinkInfo Attempt to link with target collision %wZ Target %wZ\n",
2415                               &pSrcCcb->DirectoryCB->NameInformation.FileName,
2416                               &pTargetDirEntry->NameInformation.FileName));
2417
2418                 try_return( ntStatus = STATUS_OBJECT_NAME_COLLISION);
2419             }
2420
2421             AFSDbgTrace(( AFS_SUBSYSTEM_FILE_PROCESSING | AFS_SUBSYSTEM_DIRENTRY_REF_COUNTING,
2422                           AFS_TRACE_LEVEL_ERROR,
2423                           "AFSSetFileLinkInfo Target %wZ exists DE %p Count %d, performing delete of target\n",
2424                           &pTargetDirEntry->NameInformation.FileName,
2425                           pTargetDirEntry,
2426                           lCount));
2427
2428             //
2429             // Pull the directory entry from the parent
2430             //
2431
2432             AFSRemoveDirNodeFromParent( pTargetParentObject,
2433                                         pTargetDirEntry,
2434                                         FALSE);
2435
2436             bTargetEntryExists = TRUE;
2437         }
2438         else
2439         {
2440             AFSDbgTrace(( AFS_SUBSYSTEM_FILE_PROCESSING,
2441                           AFS_TRACE_LEVEL_VERBOSE,
2442                           "AFSSetFileLinkInfo Target does NOT exist, normal linking\n"));
2443         }
2444
2445         //
2446         // OK, this is a simple rename. Issue the rename
2447         // request to the service.
2448         //
2449
2450         ntStatus = AFSNotifyHardLink( pSrcObject,
2451                                       &pSrcCcb->AuthGroup,
2452                                       pSrcParentObject,
2453                                       pTargetDcb->ObjectInformation,
2454                                       pSrcCcb->DirectoryCB,
2455                                       &uniTargetName,
2456                                       pFileLinkInfo->ReplaceIfExists,
2457                                       &pNewTargetDirEntry);
2458
2459         if( ntStatus != STATUS_REPARSE &&
2460             !NT_SUCCESS( ntStatus))
2461         {
2462
2463             AFSDbgTrace(( AFS_SUBSYSTEM_FILE_PROCESSING,
2464                           AFS_TRACE_LEVEL_ERROR,
2465                           "AFSSetFileLinkInfo Failed link of %wZ to target %wZ Status %08lX\n",
2466                           &pSrcCcb->DirectoryCB->NameInformation.FileName,
2467                           &uniTargetName,
2468                           ntStatus));
2469
2470             try_return( ntStatus);
2471         }
2472
2473         if ( ntStatus != STATUS_REPARSE)
2474         {
2475
2476             AFSInsertDirectoryNode( pTargetDcb->ObjectInformation,
2477                                     pNewTargetDirEntry,
2478                                     TRUE);
2479         }
2480
2481         //
2482         // Send notification for the target link file
2483         //
2484
2485         if( bTargetEntryExists || pNewTargetDirEntry)
2486         {
2487
2488             ulNotificationAction = FILE_ACTION_MODIFIED;
2489         }
2490         else
2491         {
2492
2493             ulNotificationAction = FILE_ACTION_ADDED;
2494         }
2495
2496         AFSFsRtlNotifyFullReportChange( pTargetParentObject,
2497                                         pSrcCcb,
2498                                         (ULONG)ulNotifyFilter,
2499                                         (ULONG)ulNotificationAction);
2500
2501       try_exit:
2502
2503         if( !NT_SUCCESS( ntStatus))
2504         {
2505
2506             if( bTargetEntryExists)
2507             {
2508
2509                 AFSInsertDirectoryNode( pTargetParentObject,
2510                                         pTargetDirEntry,
2511                                         FALSE);
2512             }
2513         }
2514
2515         if( pTargetDirEntry != NULL)
2516         {
2517
2518             //
2519             // Release DirOpenReferenceCount obtained above
2520             //
2521
2522             lCount = InterlockedDecrement( &pTargetDirEntry->DirOpenReferenceCount);
2523
2524             AFSDbgTrace(( AFS_SUBSYSTEM_DIRENTRY_REF_COUNTING,
2525                           AFS_TRACE_LEVEL_VERBOSE,
2526                           "AFSSetFileLinkInfo Decrement count on %wZ DE %p Ccb %p Cnt %d\n",
2527                           &pTargetDirEntry->NameInformation.FileName,
2528                           pTargetDirEntry,
2529                           pSrcCcb,
2530                           lCount));
2531
2532             ASSERT( lCount >= 0);
2533         }
2534
2535         if( pNewTargetDirEntry != NULL)
2536         {
2537
2538             //
2539             // Release DirOpenReferenceCount obtained from AFSNotifyHardLink
2540             //
2541
2542             lCount = InterlockedDecrement( &pNewTargetDirEntry->DirOpenReferenceCount);
2543
2544             AFSDbgTrace(( AFS_SUBSYSTEM_DIRENTRY_REF_COUNTING,
2545                           AFS_TRACE_LEVEL_VERBOSE,
2546                           "AFSSetFileLinkInfo Decrement count on %wZ DE %p Ccb %p Cnt %d\n",
2547                           &pNewTargetDirEntry->NameInformation.FileName,
2548                           pNewTargetDirEntry,
2549                           pSrcCcb,
2550                           lCount));
2551
2552             ASSERT( lCount >= 0);
2553         }
2554
2555         if( bReleaseTargetDirLock)
2556         {
2557
2558             AFSReleaseResource( pTargetParentObject->Specific.Directory.DirectoryNodeHdr.TreeLock);
2559         }
2560
2561         if ( pSrcParentObject != NULL)
2562         {
2563
2564             AFSReleaseObjectInfo( &pSrcParentObject);
2565         }
2566
2567         //
2568         // No need to release pTargetParentObject as it is either a copy of pSrcParentObject
2569         // or (AFSFcb *)pTargetFileObj->FsContext->ObjectInformation
2570         //
2571
2572         pTargetParentObject = NULL;
2573     }
2574
2575     return ntStatus;
2576 }
2577
2578 NTSTATUS
2579 AFSSetRenameInfo( IN PIRP Irp)
2580 {
2581
2582     NTSTATUS ntStatus = STATUS_SUCCESS;
2583     AFSDeviceExt *pDeviceExt = (AFSDeviceExt *)AFSRDRDeviceObject->DeviceExtension;
2584     PIO_STACK_LOCATION pIrpSp = IoGetCurrentIrpStackLocation( Irp);
2585     AFSFcb *pSrcFcb = NULL, *pTargetDcb = NULL, *pTargetFcb = NULL;
2586     AFSCcb *pSrcCcb = NULL, *pTargetDirCcb = NULL;
2587     PFILE_OBJECT pSrcFileObj = pIrpSp->FileObject;
2588     PFILE_OBJECT pTargetFileObj = pIrpSp->Parameters.SetFile.FileObject;
2589     PFILE_OBJECT pTargetParentFileObj = NULL;
2590     PFILE_RENAME_INFORMATION pRenameInfo = NULL;
2591     UNICODE_STRING uniTargetName, uniSourceName, uniTargetParentName;
2592     BOOLEAN bReplaceIfExists = FALSE;
2593     UNICODE_STRING uniShortName;
2594     AFSDirectoryCB *pTargetDirEntry = NULL;
2595     ULONG ulTargetCRC = 0;
2596     BOOLEAN bTargetEntryExists = FALSE;
2597     AFSObjectInfoCB *pSrcObject = NULL;
2598     AFSObjectInfoCB *pSrcParentObject = NULL, *pTargetParentObject = NULL;
2599     AFSFileID stNewFid;
2600     ULONG ulNotificationAction = 0, ulNotifyFilter = 0;
2601     UNICODE_STRING uniFullTargetName;
2602     BOOLEAN bCommonParent = FALSE;
2603     BOOLEAN bReleaseTargetDirLock = FALSE;
2604     BOOLEAN bReleaseSourceDirLock = FALSE;
2605     BOOLEAN bDereferenceTargetParentObject = FALSE;
2606     PERESOURCE  pSourceDirLock = NULL;
2607     LONG lCount;
2608
2609     __Enter
2610     {
2611
2612         bReplaceIfExists = pIrpSp->Parameters.SetFile.ReplaceIfExists;
2613
2614         pRenameInfo = (PFILE_RENAME_INFORMATION)Irp->AssociatedIrp.SystemBuffer;
2615
2616         pSrcFcb = (AFSFcb *)pSrcFileObj->FsContext;
2617         pSrcCcb = (AFSCcb *)pSrcFileObj->FsContext2;
2618
2619         pSrcObject = pSrcFcb->ObjectInformation;
2620
2621         if ( BooleanFlagOn( pSrcObject->Flags, AFS_OBJECT_FLAGS_PARENT_FID))
2622         {
2623
2624             pSrcParentObject = AFSFindObjectInfo( pSrcObject->VolumeCB,
2625                                                   &pSrcObject->ParentFileId,
2626                                                   TRUE);
2627         }
2628
2629         if( pSrcParentObject == NULL)
2630         {
2631
2632             AFSDbgTrace(( AFS_SUBSYSTEM_FILE_PROCESSING,
2633                           AFS_TRACE_LEVEL_ERROR,
2634                           "AFSSetRenameInfo Unable to resolve SrcParentObject (INVALID_PARAMETER)\n"));
2635
2636             ASSERT( FALSE);
2637
2638             try_return( ntStatus = STATUS_INVALID_PARAMETER);
2639         }
2640
2641         //
2642         // Perform some basic checks to ensure FS integrity
2643         //
2644
2645         if( pSrcFcb->Header.NodeTypeCode == AFS_ROOT_FCB)
2646         {
2647
2648             //
2649             // Can't rename the root directory
2650             //
2651
2652             AFSDbgTrace(( AFS_SUBSYSTEM_FILE_PROCESSING,
2653                           AFS_TRACE_LEVEL_ERROR,
2654                           "AFSSetRenameInfo Attempt to rename root entry\n"));
2655
2656             try_return( ntStatus = STATUS_INVALID_PARAMETER);
2657         }
2658
2659         if( pSrcFcb->Header.NodeTypeCode == AFS_DIRECTORY_FCB)
2660         {
2661
2662             //
2663             // If there are any open children then fail the rename
2664             //
2665
2666             if( pSrcObject->Specific.Directory.ChildOpenHandleCount > 0)
2667             {
2668
2669                 AFSDbgTrace(( AFS_SUBSYSTEM_FILE_PROCESSING,
2670                               AFS_TRACE_LEVEL_ERROR,
2671                               "AFSSetRenameInfo Attempt to rename directory with open children %wZ\n",
2672                               &pSrcCcb->DirectoryCB->NameInformation.FileName));
2673
2674                 try_return( ntStatus = STATUS_ACCESS_DENIED);
2675             }
2676         }
2677
2678
2679         //
2680         // Extract off the final component name from the Fcb
2681         //
2682
2683         uniSourceName.Length = (USHORT)pSrcCcb->DirectoryCB->NameInformation.FileName.Length;
2684         uniSourceName.MaximumLength = uniSourceName.Length;
2685
2686         uniSourceName.Buffer = pSrcCcb->DirectoryCB->NameInformation.FileName.Buffer;
2687
2688         //
2689         // Resolve the target fileobject
2690         //
2691
2692         if( pTargetFileObj == NULL)
2693         {
2694
2695             if ( pRenameInfo->RootDirectory)
2696             {
2697
2698                 AFSDbgTrace(( AFS_SUBSYSTEM_FILE_PROCESSING,
2699                               AFS_TRACE_LEVEL_ERROR,
2700                               "AFSSetRenameInfo Handle provided but no FileObject ntStatus INVALID_PARAMETER\n"));
2701
2702                 try_return( ntStatus = STATUS_INVALID_PARAMETER);
2703             }
2704             else
2705             {
2706
2707                 uniFullTargetName.Length = (USHORT)pRenameInfo->FileNameLength;
2708
2709                 uniFullTargetName.Buffer = (PWSTR)&pRenameInfo->FileName;
2710
2711                 AFSRetrieveFinalComponent( &uniFullTargetName,
2712                                            &uniTargetName);
2713
2714                 AFSRetrieveParentPath( &uniFullTargetName,
2715                                        &uniTargetParentName);
2716
2717                 if ( uniTargetParentName.Length == 0)
2718                 {
2719
2720                     //
2721                     // This is a simple rename. Here the target directory is the same as the source parent directory
2722                     // and the name is retrieved from the system buffer information
2723                     //
2724
2725                     pTargetParentObject = pSrcParentObject;
2726                 }
2727                 else
2728                 {
2729                     //
2730                     // uniTargetParentName contains the directory the renamed object
2731                     // will be moved to.  Must obtain the TargetParentObject.
2732                     //
2733
2734                     AFSDbgTrace(( AFS_SUBSYSTEM_FILE_PROCESSING,
2735                                   AFS_TRACE_LEVEL_ERROR,
2736                                   "AFSSetRenameInfo Attempt to move %wZ to %wZ -- not yet supported (NOT_SAME_DEVICE)\n",
2737                                   &pSrcCcb->DirectoryCB->NameInformation.FileName,
2738                                   &uniFullTargetName));
2739
2740                     try_return( ntStatus = STATUS_NOT_SAME_DEVICE);
2741                 }
2742             }
2743
2744             pTargetDcb = pTargetParentObject->Fcb;
2745         }
2746         else
2747         {
2748
2749             //
2750             // So here we have the target directory taken from the targetfile object
2751             //
2752
2753             pTargetDcb = (AFSFcb *)pTargetFileObj->FsContext;
2754
2755             pTargetDirCcb = (AFSCcb *)pTargetFileObj->FsContext2;
2756
2757             pTargetParentObject = (AFSObjectInfoCB *)pTargetDcb->ObjectInformation;
2758
2759             //
2760             // Grab the target name which we setup in the IRP_MJ_CREATE handler. By how we set this up
2761             // it is only the target component of the rename operation
2762             //
2763
2764             uniTargetName = *((PUNICODE_STRING)&pTargetFileObj->FileName);
2765         }
2766
2767         //
2768         // The quick check to see if they are not really performing a rename
2769         // Do the names match? Only do this where the parent directories are
2770         // the same
2771         //
2772
2773         if( pTargetParentObject == pSrcParentObject)
2774         {
2775
2776             if( FsRtlAreNamesEqual( &uniTargetName,
2777                                     &uniSourceName,
2778                                     FALSE,
2779                                     NULL))
2780             {
2781                 try_return( ntStatus = STATUS_SUCCESS);
2782             }
2783
2784             bCommonParent = TRUE;
2785         }
2786         else
2787         {
2788
2789             bCommonParent = FALSE;
2790         }
2791
2792         //
2793         // We do not allow cross-volume renames to occur
2794         //
2795
2796         if( pTargetParentObject->VolumeCB != pSrcObject->VolumeCB)
2797         {
2798
2799             AFSDbgTrace(( AFS_SUBSYSTEM_FILE_PROCESSING,
2800                           AFS_TRACE_LEVEL_ERROR,
2801                           "AFSSetRenameInfo Attempt to rename directory to different volume %wZ\n",
2802                           &pSrcCcb->DirectoryCB->NameInformation.FileName));
2803
2804             try_return( ntStatus = STATUS_NOT_SAME_DEVICE);
2805         }
2806
2807         ulTargetCRC = AFSGenerateCRC( &uniTargetName,
2808                                       FALSE);
2809
2810         AFSAcquireExcl( pTargetParentObject->Specific.Directory.DirectoryNodeHdr.TreeLock,
2811                         TRUE);
2812
2813         bReleaseTargetDirLock = TRUE;
2814
2815         if( pTargetParentObject != pSrcParentObject)
2816         {
2817             AFSAcquireExcl( pSrcParentObject->Specific.Directory.DirectoryNodeHdr.TreeLock,
2818                             TRUE);
2819
2820             bReleaseSourceDirLock = TRUE;
2821
2822             pSourceDirLock = pSrcParentObject->Specific.Directory.DirectoryNodeHdr.TreeLock;
2823         }
2824
2825         AFSLocateCaseSensitiveDirEntry( pTargetParentObject->Specific.Directory.DirectoryNodeHdr.CaseSensitiveTreeHead,
2826                                         ulTargetCRC,
2827                                         &pTargetDirEntry);
2828
2829         if( pTargetDirEntry == NULL)
2830         {
2831
2832             //
2833             // Missed so perform a case insensitive lookup
2834             //
2835
2836             ulTargetCRC = AFSGenerateCRC( &uniTargetName,
2837                                           TRUE);
2838
2839             AFSLocateCaseInsensitiveDirEntry( pTargetParentObject->Specific.Directory.DirectoryNodeHdr.CaseInsensitiveTreeHead,
2840                                               ulTargetCRC,
2841                                               &pTargetDirEntry);
2842         }
2843
2844         if ( !BooleanFlagOn( pDeviceExt->DeviceFlags, AFS_DEVICE_FLAG_DISABLE_SHORTNAMES) &&
2845              pTargetDirEntry == NULL && RtlIsNameLegalDOS8Dot3( &uniTargetName,
2846                                                                NULL,
2847                                                                NULL))
2848         {
2849             //
2850             // Try the short name
2851             //
2852             AFSLocateShortNameDirEntry( pTargetParentObject->Specific.Directory.ShortNameTree,
2853                                         ulTargetCRC,
2854                                         &pTargetDirEntry);
2855         }
2856
2857         //
2858         // Increment our ref count on the dir entry
2859         //
2860
2861         if( pTargetDirEntry != NULL)
2862         {
2863
2864             ASSERT( BooleanFlagOn( pTargetDirEntry->ObjectInformation->Flags, AFS_OBJECT_FLAGS_PARENT_FID) &&
2865                     AFSIsEqualFID( &pTargetParentObject->FileId, &pTargetDirEntry->ObjectInformation->ParentFileId));
2866
2867             lCount = InterlockedIncrement( &pTargetDirEntry->DirOpenReferenceCount);
2868
2869             AFSDbgTrace(( AFS_SUBSYSTEM_DIRENTRY_REF_COUNTING,
2870                           AFS_TRACE_LEVEL_VERBOSE,
2871                           "AFSSetRenameInfo Increment count on %wZ DE %p Ccb %p Cnt %d\n",
2872                           &pTargetDirEntry->NameInformation.FileName,
2873                           pTargetDirEntry,
2874                           pSrcCcb,
2875                           lCount));
2876
2877             ASSERT( lCount >= 0);
2878
2879             if( !bReplaceIfExists)
2880             {
2881
2882                 AFSDbgTrace(( AFS_SUBSYSTEM_FILE_PROCESSING,
2883                               AFS_TRACE_LEVEL_ERROR,
2884                               "AFSSetRenameInfo Attempt to rename directory with target collision %wZ Target %wZ\n",
2885                               &pSrcCcb->DirectoryCB->NameInformation.FileName,
2886                               &pTargetDirEntry->NameInformation.FileName));
2887
2888                 try_return( ntStatus = STATUS_OBJECT_NAME_COLLISION);
2889             }
2890
2891             AFSDbgTrace(( AFS_SUBSYSTEM_FILE_PROCESSING | AFS_SUBSYSTEM_DIRENTRY_REF_COUNTING,
2892                           AFS_TRACE_LEVEL_ERROR,
2893                           "AFSSetRenameInfo Target %wZ exists DE %p Count %d, performing delete of target\n",
2894                           &pTargetDirEntry->NameInformation.FileName,
2895                           pTargetDirEntry,
2896                           lCount));
2897
2898             //
2899             // Pull the directory entry from the parent
2900             //
2901
2902             AFSRemoveDirNodeFromParent( pTargetParentObject,
2903                                         pTargetDirEntry,
2904                                         FALSE);
2905
2906             bTargetEntryExists = TRUE;
2907         }
2908         else
2909         {
2910             AFSDbgTrace(( AFS_SUBSYSTEM_FILE_PROCESSING,
2911                           AFS_TRACE_LEVEL_VERBOSE,
2912                           "AFSSetRenameInfo Target does NOT exist, normal rename\n"));
2913         }
2914
2915         //
2916         // We need to remove the DirEntry from the parent node, update the index
2917         // and reinsert it into the parent tree. Note that for entries with the
2918         // same parent we do not pull the node from the enumeration list
2919         //
2920
2921         AFSRemoveDirNodeFromParent( pSrcParentObject,
2922                                     pSrcCcb->DirectoryCB,
2923                                     !bCommonParent);
2924
2925         //
2926         // OK, this is a simple rename. Issue the rename
2927         // request to the service.
2928         //
2929
2930         ntStatus = AFSNotifyRename( pSrcObject,
2931                                     &pSrcCcb->AuthGroup,
2932                                     pSrcParentObject,
2933                                     pTargetDcb->ObjectInformation,
2934                                     pSrcCcb->DirectoryCB,
2935                                     &uniTargetName,
2936                                     &stNewFid);
2937
2938         if( !NT_SUCCESS( ntStatus))
2939         {
2940
2941             //
2942             // Attempt to re-insert the directory entry
2943             //
2944
2945             AFSInsertDirectoryNode( pSrcParentObject,
2946                                     pSrcCcb->DirectoryCB,
2947                                     !bCommonParent);
2948
2949             AFSDbgTrace(( AFS_SUBSYSTEM_FILE_PROCESSING,
2950                           AFS_TRACE_LEVEL_ERROR,
2951                           "AFSSetRenameInfo Failed rename of %wZ to target %wZ Status %08lX\n",
2952                           &pSrcCcb->DirectoryCB->NameInformation.FileName,
2953                           &uniTargetName,
2954                           ntStatus));
2955
2956             try_return( ntStatus);
2957         }
2958
2959         //
2960         // Set the notification up for the source file
2961         //
2962
2963         if( pSrcParentObject == pTargetParentObject &&
2964             !bTargetEntryExists)
2965         {
2966
2967             ulNotificationAction = FILE_ACTION_RENAMED_OLD_NAME;
2968         }
2969         else
2970         {
2971
2972             ulNotificationAction = FILE_ACTION_REMOVED;
2973         }
2974
2975         if( pSrcObject->FileType == AFS_FILE_TYPE_DIRECTORY)
2976         {
2977
2978             ulNotifyFilter = FILE_NOTIFY_CHANGE_DIR_NAME;
2979         }
2980         else
2981         {
2982
2983             ulNotifyFilter = FILE_NOTIFY_CHANGE_FILE_NAME;
2984         }
2985
2986         AFSFsRtlNotifyFullReportChange( pSrcParentObject,
2987                                         pSrcCcb,
2988                                         (ULONG)ulNotifyFilter,
2989                                         (ULONG)ulNotificationAction);
2990
2991         //
2992         // Update the name in the dir entry.
2993         //
2994
2995         ntStatus = AFSUpdateDirEntryName( pSrcCcb->DirectoryCB,
2996                                           &uniTargetName);
2997
2998         if( !NT_SUCCESS( ntStatus))
2999         {
3000
3001             //
3002             // Attempt to re-insert the directory entry
3003             //
3004
3005             AFSInsertDirectoryNode( pSrcParentObject,
3006                                     pSrcCcb->DirectoryCB,
3007                                     !bCommonParent);
3008
3009             AFSDbgTrace(( AFS_SUBSYSTEM_FILE_PROCESSING,
3010                           AFS_TRACE_LEVEL_ERROR,
3011                           "AFSSetRenameInfo Failed update of dir entry %wZ to target %wZ Status %08lX\n",
3012                           &pSrcCcb->DirectoryCB->NameInformation.FileName,
3013                           &uniTargetName,
3014                           ntStatus));
3015
3016             try_return( ntStatus);
3017         }
3018
3019         //
3020         // Update the object information block, if needed
3021         //
3022
3023         if( !AFSIsEqualFID( &pSrcObject->FileId,
3024                             &stNewFid))
3025         {
3026
3027             AFSAcquireExcl( pSrcObject->VolumeCB->ObjectInfoTree.TreeLock,
3028                             TRUE);
3029
3030             //
3031             // Remove the old information entry
3032             //
3033
3034             AFSRemoveHashEntry( &pSrcObject->VolumeCB->ObjectInfoTree.TreeHead,
3035                                 &pSrcObject->TreeEntry);
3036
3037             RtlCopyMemory( &pSrcObject->FileId,
3038                            &stNewFid,
3039                            sizeof( AFSFileID));
3040
3041             //
3042             // Insert the entry into the new object table.
3043             //
3044
3045             pSrcObject->TreeEntry.HashIndex = AFSCreateLowIndex( &pSrcObject->FileId);
3046
3047             if( pSrcObject->VolumeCB->ObjectInfoTree.TreeHead == NULL)
3048             {
3049
3050                 pSrcObject->VolumeCB->ObjectInfoTree.TreeHead = &pSrcObject->TreeEntry;
3051             }
3052             else
3053             {
3054
3055                 if ( !NT_SUCCESS( AFSInsertHashEntry( pSrcObject->VolumeCB->ObjectInfoTree.TreeHead,
3056                                                      &pSrcObject->TreeEntry)))
3057                 {
3058
3059                     //
3060                     // Lost a race, an ObjectInfo object already exists for this FID.
3061                     // Let this copy be garbage collected.
3062                     //
3063
3064                     ClearFlag( pSrcObject->Flags, AFS_OBJECT_INSERTED_HASH_TREE);
3065                 }
3066             }
3067
3068             AFSReleaseResource( pSrcObject->VolumeCB->ObjectInfoTree.TreeLock);
3069         }
3070
3071         //
3072         // Update the hash values for the name trees.
3073         //
3074
3075         pSrcCcb->DirectoryCB->CaseSensitiveTreeEntry.HashIndex = AFSGenerateCRC( &pSrcCcb->DirectoryCB->NameInformation.FileName,
3076                                                                                  FALSE);
3077
3078         pSrcCcb->DirectoryCB->CaseInsensitiveTreeEntry.HashIndex = AFSGenerateCRC( &pSrcCcb->DirectoryCB->NameInformation.FileName,
3079                                                                                    TRUE);
3080
3081         if( !BooleanFlagOn( pDeviceExt->DeviceFlags, AFS_DEVICE_FLAG_DISABLE_SHORTNAMES) &&
3082             pSrcCcb->DirectoryCB->NameInformation.ShortNameLength > 0 &&
3083             !RtlIsNameLegalDOS8Dot3( &pSrcCcb->DirectoryCB->NameInformation.FileName,
3084                                      NULL,
3085                                      NULL))
3086         {
3087
3088             uniShortName.Length = pSrcCcb->DirectoryCB->NameInformation.ShortNameLength;
3089             uniShortName.MaximumLength = uniShortName.Length;
3090             uniShortName.Buffer = pSrcCcb->DirectoryCB->NameInformation.ShortName;
3091
3092             pSrcCcb->DirectoryCB->Type.Data.ShortNameTreeEntry.HashIndex = AFSGenerateCRC( &uniShortName,
3093                                                                                            TRUE);
3094
3095             AFSDbgTrace(( AFS_SUBSYSTEM_FILE_PROCESSING,
3096                           AFS_TRACE_LEVEL_VERBOSE,
3097                           "AFSSetRenameInfo Initialized short name hash for %wZ longname %wZ\n",
3098                           &uniShortName,
3099                           &pSrcCcb->DirectoryCB->NameInformation.FileName));
3100         }
3101         else
3102         {
3103
3104             pSrcCcb->DirectoryCB->Type.Data.ShortNameTreeEntry.HashIndex = 0;
3105         }
3106
3107         if( !bCommonParent)
3108         {
3109
3110             //
3111             // Update the file index for the object in the new parent
3112             //
3113
3114             pSrcCcb->DirectoryCB->FileIndex = (ULONG)InterlockedIncrement( &pTargetParentObject->Specific.Directory.DirectoryNodeHdr.ContentIndex);
3115         }
3116
3117         //
3118         // Re-insert the directory entry
3119         //
3120
3121         AFSInsertDirectoryNode( pTargetParentObject,
3122                                 pSrcCcb->DirectoryCB,
3123                                 !bCommonParent);
3124
3125         //
3126         // Update the parent pointer in the source object if they are different
3127         //
3128
3129         if( pSrcParentObject != pTargetParentObject)
3130         {
3131
3132             lCount = InterlockedDecrement( &pSrcParentObject->Specific.Directory.ChildOpenHandleCount);
3133
3134             lCount = InterlockedDecrement( &pSrcParentObject->Specific.Directory.ChildOpenReferenceCount);
3135
3136             lCount = InterlockedIncrement( &pTargetParentObject->Specific.Directory.ChildOpenHandleCount);
3137
3138             lCount = InterlockedIncrement( &pTargetParentObject->Specific.Directory.ChildOpenReferenceCount);
3139
3140
3141             //
3142             // Guaranteed to be in the same volume
3143             //
3144
3145             AFSAcquireExcl( pSrcParentObject->VolumeCB->ObjectInfoTree.TreeLock,
3146                             TRUE);
3147
3148             lCount = AFSObjectInfoIncrement( pTargetParentObject,
3149                                              AFS_OBJECT_REFERENCE_CHILD);
3150
3151             AFSDbgTrace(( AFS_SUBSYSTEM_OBJECT_REF_COUNTING,
3152                           AFS_TRACE_LEVEL_VERBOSE,
3153                           "AFSSetRenameInfo Increment count on parent object %p Cnt %d\n",
3154                           pTargetParentObject,
3155                           lCount));
3156
3157             lCount = AFSObjectInfoDecrement( pSrcParentObject,
3158                                              AFS_OBJECT_REFERENCE_CHILD);
3159
3160             AFSDbgTrace(( AFS_SUBSYSTEM_OBJECT_REF_COUNTING,
3161                           AFS_TRACE_LEVEL_VERBOSE,
3162                           "AFSSetRenameInfo Decrement count on parent object %p Cnt %d\n",
3163                           pSrcParentObject,
3164                           lCount));
3165
3166             pSrcObject->ParentFileId = pTargetParentObject->FileId;
3167
3168             SetFlag( pSrcObject->Flags, AFS_OBJECT_FLAGS_PARENT_FID);
3169
3170             AFSReleaseResource( pSrcParentObject->VolumeCB->ObjectInfoTree.TreeLock);
3171
3172             ulNotificationAction = FILE_ACTION_ADDED;
3173         }
3174         else
3175         {
3176
3177             ulNotificationAction = FILE_ACTION_RENAMED_NEW_NAME;
3178         }
3179
3180         //
3181         // Now update the notification for the target file
3182         //
3183
3184         AFSFsRtlNotifyFullReportChange( pTargetParentObject,
3185                                         pSrcCcb,
3186                                         (ULONG)ulNotifyFilter,
3187                                         (ULONG)ulNotificationAction);
3188
3189         //
3190         // If we performed the rename of the target because it existed, we now need to
3191         // delete the tmp target we created above
3192         //
3193
3194         if( bTargetEntryExists)
3195         {
3196
3197             AFSDbgTrace(( AFS_SUBSYSTEM_FILE_PROCESSING,
3198                           AFS_TRACE_LEVEL_VERBOSE,
3199                           "AFSSetRenameInfo Setting DELETE flag in dir entry %p name %wZ\n",
3200                           pTargetDirEntry,
3201                           &pTargetDirEntry->NameInformation.FileName));
3202
3203             SetFlag( pTargetDirEntry->Flags, AFS_DIR_ENTRY_DELETED);
3204
3205             //
3206             // Try and purge the cache map if this is a file
3207             //
3208
3209             if( pTargetDirEntry->ObjectInformation->FileType == AFS_FILE_TYPE_FILE &&
3210                 pTargetDirEntry->ObjectInformation->Fcb != NULL &&
3211                 pTargetDirEntry->DirOpenReferenceCount > 1)
3212             {
3213
3214                 pTargetFcb = pTargetDirEntry->ObjectInformation->Fcb;
3215             }
3216
3217             ASSERT( pTargetDirEntry->DirOpenReferenceCount > 0);
3218
3219             lCount = InterlockedDecrement( &pTargetDirEntry->DirOpenReferenceCount); // The count we added above
3220
3221             AFSDbgTrace(( AFS_SUBSYSTEM_DIRENTRY_REF_COUNTING,
3222                           AFS_TRACE_LEVEL_VERBOSE,
3223                           "AFSSetRenameInfo Decrement count on %wZ DE %p Ccb %p Cnt %d\n",
3224                           &pTargetDirEntry->NameInformation.FileName,
3225                           pTargetDirEntry,
3226                           pSrcCcb,
3227                           lCount));
3228
3229             ASSERT( lCount >= 0);
3230
3231             if( lCount == 0 &&
3232                 pTargetDirEntry->NameArrayReferenceCount <= 0)
3233             {
3234
3235                 AFSDbgTrace(( AFS_SUBSYSTEM_FILE_PROCESSING,
3236                               AFS_TRACE_LEVEL_VERBOSE,
3237                               "AFSSetRenameInfo Deleting dir entry %p name %wZ\n",
3238                               pTargetDirEntry,
3239                               &pTargetDirEntry->NameInformation.FileName));
3240
3241                 AFSDeleteDirEntry( pTargetParentObject,
3242                                    &pTargetDirEntry);
3243             }
3244
3245             pTargetDirEntry = NULL;
3246
3247             if ( pTargetFcb != NULL)
3248             {
3249
3250                 //
3251                 // Do not hold TreeLocks across the MmForceSectionClosed() call as
3252                 // it can deadlock with Trend Micro's TmPreFlt!TmpQueryFullName
3253                 //
3254
3255                 if( bReleaseTargetDirLock)
3256                 {
3257                     AFSReleaseResource( pTargetParentObject->Specific.Directory.DirectoryNodeHdr.TreeLock);
3258
3259                     bReleaseTargetDirLock = FALSE;
3260                 }
3261
3262                 if( bReleaseSourceDirLock)
3263                 {
3264
3265                     AFSReleaseResource( pSourceDirLock);
3266
3267                     bReleaseSourceDirLock = FALSE;
3268                 }
3269
3270                 //
3271                 // MmForceSectionClosed() can eventually call back into AFSCleanup
3272                 // which will need to acquire Fcb->Resource exclusively.  Failure
3273                 // to obtain it here before holding the SectionObjectResource will
3274                 // permit the locks to be obtained out of order risking a deadlock.
3275                 //
3276
3277                 AFSDbgTrace(( AFS_SUBSYSTEM_LOCK_PROCESSING|AFS_SUBSYSTEM_SECTION_OBJECT,
3278                               AFS_TRACE_LEVEL_VERBOSE,
3279                               "AFSSetRenameInfo Acquiring Fcb lock %p EXCL %08lX\n",
3280                               &pTargetFcb->NPFcb->Resource,
3281                               PsGetCurrentThread()));
3282
3283                 AFSAcquireExcl( &pTargetFcb->NPFcb->Resource,
3284                                 TRUE);
3285
3286                 AFSDbgTrace(( AFS_SUBSYSTEM_LOCK_PROCESSING|AFS_SUBSYSTEM_SECTION_OBJECT,
3287                               AFS_TRACE_LEVEL_VERBOSE,
3288                               "AFSSetRenameInfo Acquiring Fcb SectionObject lock %p EXCL %08lX\n",
3289                               &pTargetFcb->NPFcb->SectionObjectResource,
3290                               PsGetCurrentThread()));
3291
3292                 AFSAcquireExcl( &pTargetFcb->NPFcb->SectionObjectResource,
3293                                 TRUE);
3294
3295                 __try
3296                 {
3297
3298                     //
3299                     // Close the section in the event it was mapped
3300                     //
3301
3302                     if( !MmForceSectionClosed( &pTargetFcb->NPFcb->SectionObjectPointers,
3303                                                TRUE))
3304                     {
3305
3306                         AFSDbgTrace(( AFS_SUBSYSTEM_FILE_PROCESSING,
3307                                       AFS_TRACE_LEVEL_ERROR,
3308                                       "AFSSetRenameInfo Failed to delete section for target file %wZ\n",
3309                                       &uniTargetName));
3310                     }
3311                 }
3312                 __except( AFSExceptionFilter( __FUNCTION__, GetExceptionCode(), GetExceptionInformation()))
3313                 {
3314
3315                     ntStatus = GetExceptionCode();
3316
3317                     AFSDbgTrace(( 0,
3318                                   0,
3319                                   "EXCEPTION - AFSSetRenameInfo MmForceSectionClosed failed FID %08lX-%08lX-%08lX-%08lX Status 0x%08lX\n",
3320                                   pTargetFcb->ObjectInformation->FileId.Cell,
3321                                   pTargetFcb->ObjectInformation->FileId.Volume,
3322                                   pTargetFcb->ObjectInformation->FileId.Vnode,
3323                                   pTargetFcb->ObjectInformation->FileId.Unique,
3324                                   ntStatus));
3325                 }
3326
3327                 AFSDbgTrace(( AFS_SUBSYSTEM_LOCK_PROCESSING|AFS_SUBSYSTEM_SECTION_OBJECT,
3328                               AFS_TRACE_LEVEL_VERBOSE,
3329                               "AFSSetRenameInfo Releasing Fcb SectionObject lock %p EXCL %08lX\n",
3330                               &pTargetFcb->NPFcb->SectionObjectResource,
3331                               PsGetCurrentThread()));
3332
3333                 AFSReleaseResource( &pTargetFcb->NPFcb->SectionObjectResource);
3334
3335                 AFSDbgTrace(( AFS_SUBSYSTEM_LOCK_PROCESSING,
3336                               AFS_TRACE_LEVEL_VERBOSE,
3337                               "AFSSetRenameInfo Releasing Fcb lock %p EXCL %08lX\n",
3338                               &pTargetFcb->NPFcb->Resource,
3339                               PsGetCurrentThread()));
3340
3341                 AFSReleaseResource( &pTargetFcb->NPFcb->Resource);
3342             }
3343         }
3344
3345 try_exit:
3346
3347         if( !NT_SUCCESS( ntStatus))
3348         {
3349
3350             if( bTargetEntryExists)
3351             {
3352
3353                 ASSERT( pTargetParentObject != NULL);
3354
3355                 AFSInsertDirectoryNode( pTargetParentObject,
3356                                         pTargetDirEntry,
3357                                         FALSE);
3358             }
3359         }
3360
3361         if( pTargetDirEntry != NULL)
3362         {
3363
3364             lCount = InterlockedDecrement( &pTargetDirEntry->DirOpenReferenceCount);
3365
3366             AFSDbgTrace(( AFS_SUBSYSTEM_DIRENTRY_REF_COUNTING,
3367                           AFS_TRACE_LEVEL_VERBOSE,
3368                           "AFSSetRenameInfo Decrement2 count on %wZ DE %p Ccb %p Cnt %d\n",
3369                           &pTargetDirEntry->NameInformation.FileName,
3370                           pTargetDirEntry,
3371                           pSrcCcb,
3372                           lCount));
3373
3374             ASSERT( lCount >= 0);
3375         }
3376
3377         if( bReleaseTargetDirLock)
3378         {
3379
3380             AFSReleaseResource( pTargetParentObject->Specific.Directory.DirectoryNodeHdr.TreeLock);
3381         }
3382
3383         if( bReleaseSourceDirLock)
3384         {
3385
3386             AFSReleaseResource( pSourceDirLock);
3387         }
3388
3389         if ( bDereferenceTargetParentObject)
3390         {
3391
3392             ObDereferenceObject( pTargetParentFileObj);
3393         }
3394
3395         if ( pSrcParentObject != NULL)
3396         {
3397
3398             AFSReleaseObjectInfo( &pSrcParentObject);
3399         }
3400
3401         //
3402         // No need to release pTargetParentObject as it is either a copy of pSrcParentObject
3403         // or (AFSFcb *)pTargetFileObj->FsContext->ObjectInformation
3404         //
3405
3406         pTargetParentObject = NULL;
3407     }
3408
3409     return ntStatus;
3410 }
3411
3412 NTSTATUS
3413 AFSSetPositionInfo( IN PIRP Irp,
3414                     IN AFSDirectoryCB *DirectoryCB)
3415 {
3416     UNREFERENCED_PARAMETER(DirectoryCB);
3417     NTSTATUS ntStatus = STATUS_SUCCESS;
3418     PFILE_POSITION_INFORMATION pBuffer;
3419     PIO_STACK_LOCATION pIrpSp = IoGetCurrentIrpStackLocation( Irp);
3420
3421     pBuffer = (PFILE_POSITION_INFORMATION)Irp->AssociatedIrp.SystemBuffer;
3422
3423     pIrpSp->FileObject->CurrentByteOffset.QuadPart = pBuffer->CurrentByteOffset.QuadPart;
3424
3425     return ntStatus;
3426 }
3427
3428 NTSTATUS
3429 AFSSetAllocationInfo( IN PIRP Irp,
3430                       IN AFSDirectoryCB *DirectoryCB)
3431 {
3432     UNREFERENCED_PARAMETER(DirectoryCB);
3433     NTSTATUS ntStatus = STATUS_SUCCESS;
3434     PFILE_ALLOCATION_INFORMATION pBuffer;
3435     BOOLEAN bReleasePaging = FALSE;
3436     BOOLEAN bTellCc = FALSE;
3437     BOOLEAN bTellService = FALSE;
3438     BOOLEAN bUserMapped = FALSE;
3439     PIO_STACK_LOCATION pIrpSp = IoGetCurrentIrpStackLocation( Irp);
3440     PFILE_OBJECT pFileObject = pIrpSp->FileObject;
3441     AFSFcb *pFcb = NULL;
3442     AFSCcb *pCcb = NULL;
3443     LARGE_INTEGER liSaveAlloc;
3444     LARGE_INTEGER liSaveFileSize;
3445     LARGE_INTEGER liSaveVDL;
3446
3447     pBuffer = (PFILE_ALLOCATION_INFORMATION)Irp->AssociatedIrp.SystemBuffer;
3448
3449     pFcb = (AFSFcb *)pIrpSp->FileObject->FsContext;
3450
3451     pCcb = (AFSCcb *)pIrpSp->FileObject->FsContext2;
3452
3453     //
3454     // save values to put back
3455     //
3456     liSaveAlloc = pFcb->Header.AllocationSize;
3457     liSaveFileSize = pFcb->Header.FileSize;
3458     liSaveVDL = pFcb->Header.ValidDataLength;
3459
3460     if( pFcb->Header.AllocationSize.QuadPart == pBuffer->AllocationSize.QuadPart ||
3461         pIrpSp->Parameters.SetFile.AdvanceOnly)
3462     {
3463         return STATUS_SUCCESS ;
3464     }
3465
3466     if( pFcb->Header.AllocationSize.QuadPart > pBuffer->AllocationSize.QuadPart)
3467     {
3468
3469         AFSDbgTrace(( AFS_SUBSYSTEM_LOCK_PROCESSING|AFS_SUBSYSTEM_SECTION_OBJECT,
3470                       AFS_TRACE_LEVEL_VERBOSE,
3471                       "AFSSetAllocationInfo Acquiring Fcb SectionObject lock %p EXCL %08lX\n",
3472                       &pFcb->NPFcb->SectionObjectResource,
3473                       PsGetCurrentThread()));
3474
3475         AFSAcquireExcl( &pFcb->NPFcb->SectionObjectResource,
3476                         TRUE);
3477
3478         __try
3479         {
3480
3481             bUserMapped = !MmCanFileBeTruncated( pFileObject->SectionObjectPointer,
3482                                                  &pBuffer->AllocationSize);
3483         }
3484         __except( AFSExceptionFilter( __FUNCTION__, GetExceptionCode(), GetExceptionInformation()))
3485         {
3486
3487             bUserMapped = FALSE;
3488
3489             ntStatus = GetExceptionCode();
3490
3491             AFSDbgTrace(( 0,
3492                           0,
3493                           "EXCEPTION - AFSSetAllocationInfo MmCanFileBeTruncated failed FID %08lX-%08lX-%08lX-%08lX Status 0x%08lX\n",
3494                           pFcb->ObjectInformation->FileId.Cell,
3495                           pFcb->ObjectInformation->FileId.Volume,
3496                           pFcb->ObjectInformation->FileId.Vnode,
3497                           pFcb->ObjectInformation->FileId.Unique,
3498                           ntStatus));
3499         }
3500
3501         AFSDbgTrace(( AFS_SUBSYSTEM_LOCK_PROCESSING|AFS_SUBSYSTEM_SECTION_OBJECT,
3502                       AFS_TRACE_LEVEL_VERBOSE,
3503                       "AFSSetAllocationInfo Releasing Fcb SectionObject lock %p EXCL %08lX\n",
3504                       &pFcb->NPFcb->SectionObjectResource,
3505                       PsGetCurrentThread()));
3506
3507         AFSReleaseResource( &pFcb->NPFcb->SectionObjectResource);
3508
3509         //
3510         // Truncating the file
3511         //
3512         if ( bUserMapped)
3513         {
3514
3515             ntStatus = STATUS_USER_MAPPED_FILE ;
3516         }
3517         else
3518         {
3519
3520             //
3521             // If this is a truncation we need to grab the paging IO resource.
3522             //
3523
3524             AFSDbgTrace(( AFS_SUBSYSTEM_LOCK_PROCESSING,
3525                           AFS_TRACE_LEVEL_VERBOSE,
3526                           "AFSSetAllocationInfo Acquiring Fcb PagingIo lock %p EXCL %08lX\n",
3527                           &pFcb->NPFcb->PagingResource,
3528                           PsGetCurrentThread()));
3529
3530             AFSAcquireExcl( &pFcb->NPFcb->PagingResource,
3531                             TRUE);
3532
3533             bReleasePaging = TRUE;
3534
3535             //
3536             // Must drop the Fcb Resource.  When changing the file size
3537             // a deadlock can occur with Trend Micro's filter if the file
3538             // size is set to zero.
3539             //
3540
3541             AFSReleaseResource( &pFcb->NPFcb->Resource);
3542
3543             pFcb->Header.AllocationSize = pBuffer->AllocationSize;
3544
3545             pFcb->ObjectInformation->AllocationSize = pBuffer->AllocationSize;
3546
3547             //
3548             // Tell Cc that Allocation is moved.
3549             //
3550             bTellCc = TRUE;
3551
3552             if( pFcb->Header.FileSize.QuadPart > pBuffer->AllocationSize.QuadPart)
3553             {
3554                 //
3555                 // We are pulling the EOF back as well so we need to tell
3556                 // the service.
3557                 //
3558                 bTellService = TRUE;
3559
3560                 pFcb->Header.FileSize = pBuffer->AllocationSize;
3561
3562                 pFcb->ObjectInformation->EndOfFile = pBuffer->AllocationSize;
3563             }
3564
3565         }
3566     }
3567     else
3568     {
3569         //
3570         // Tell Cc if allocation is increased.
3571         //
3572
3573         AFSDbgTrace(( AFS_SUBSYSTEM_LOCK_PROCESSING,
3574                       AFS_TRACE_LEVEL_VERBOSE,
3575                       "AFSSetAllocationInfo Acquiring Fcb PagingIo lock %p EXCL %08lX\n",
3576                       &pFcb->NPFcb->PagingResource,
3577                       PsGetCurrentThread()));
3578
3579         AFSAcquireExcl( &pFcb->NPFcb->PagingResource,
3580                         TRUE);
3581
3582         bReleasePaging = TRUE;
3583
3584         //
3585         // Must drop the Fcb Resource.  When changing the file size
3586         // a deadlock can occur with Trend Micro's filter if the file
3587         // size is set to zero.
3588         //
3589
3590         AFSReleaseResource( &pFcb->NPFcb->Resource);
3591
3592         bTellCc = pBuffer->AllocationSize.QuadPart > pFcb->Header.AllocationSize.QuadPart;
3593
3594         pFcb->Header.AllocationSize = pBuffer->AllocationSize;
3595
3596         pFcb->ObjectInformation->AllocationSize = pBuffer->AllocationSize;
3597     }
3598
3599     //
3600     // Now Tell the server if we have to
3601     //
3602     if (bTellService)
3603     {
3604
3605         ASSERT( BooleanFlagOn( pFcb->ObjectInformation->Flags, AFS_OBJECT_FLAGS_PARENT_FID));
3606
3607         ntStatus = AFSUpdateFileInformation( &pFcb->ObjectInformation->ParentFileId,
3608                                              pFcb->ObjectInformation,
3609                                              &pCcb->AuthGroup);
3610     }
3611
3612     if (NT_SUCCESS(ntStatus))
3613     {
3614         //
3615         // Trim extents if we told the service - the update has done an implicit
3616         // trim at the service.
3617         //
3618         if (bTellService)
3619         {
3620             AFSTrimExtents( pFcb,
3621                             &pFcb->Header.FileSize);
3622         }
3623
3624         KeQuerySystemTime( &pFcb->ObjectInformation->ChangeTime);
3625
3626         SetFlag( pFcb->Flags, AFS_FCB_FLAG_FILE_MODIFIED | AFS_FCB_FLAG_UPDATE_CHANGE_TIME);
3627
3628         if (bTellCc &&
3629             CcIsFileCached( pFileObject))
3630         {
3631             CcSetFileSizes( pFileObject,
3632                             (PCC_FILE_SIZES)&pFcb->Header.AllocationSize);
3633         }
3634
3635         //
3636         // Mark the file as modified so as to reflect the change into the last write on close.
3637         //
3638         SetFlag( pFileObject->Flags, FO_FILE_MODIFIED);
3639     }
3640     else
3641     {
3642         //
3643         // Put the saved values back
3644         //
3645         pFcb->Header.ValidDataLength = liSaveVDL;
3646         pFcb->Header.FileSize = liSaveFileSize;
3647         pFcb->Header.AllocationSize = liSaveAlloc;
3648         pFcb->ObjectInformation->EndOfFile = liSaveFileSize;
3649         pFcb->ObjectInformation->AllocationSize = liSaveAlloc;
3650     }
3651
3652     if( bReleasePaging)
3653     {
3654
3655         AFSReleaseResource( &pFcb->NPFcb->PagingResource);
3656
3657         AFSAcquireExcl( &pFcb->NPFcb->Resource,
3658                         TRUE);
3659     }
3660
3661     return ntStatus;
3662 }
3663
3664 NTSTATUS
3665 AFSSetEndOfFileInfo( IN PIRP Irp,
3666                      IN AFSDirectoryCB *DirectoryCB)
3667 {
3668     UNREFERENCED_PARAMETER(DirectoryCB);
3669     NTSTATUS ntStatus = STATUS_SUCCESS;
3670     PFILE_END_OF_FILE_INFORMATION pBuffer;
3671     PIO_STACK_LOCATION pIrpSp = IoGetCurrentIrpStackLocation( Irp);
3672     PFILE_OBJECT pFileObject = pIrpSp->FileObject;
3673     LARGE_INTEGER liSaveSize;
3674     LARGE_INTEGER liSaveVDL;
3675     LARGE_INTEGER liSaveAlloc;
3676     BOOLEAN bModified = FALSE;
3677     BOOLEAN bReleasePaging = FALSE;
3678     BOOLEAN bTruncated = FALSE;
3679     BOOLEAN bUserMapped = FALSE;
3680     AFSFcb *pFcb = NULL;
3681     AFSCcb *pCcb = NULL;
3682
3683     pFcb = (AFSFcb *)pIrpSp->FileObject->FsContext;
3684
3685     pCcb = (AFSCcb *)pIrpSp->FileObject->FsContext2;
3686
3687     pBuffer = (PFILE_END_OF_FILE_INFORMATION)Irp->AssociatedIrp.SystemBuffer;
3688
3689     liSaveSize = pFcb->Header.FileSize;
3690     liSaveAlloc = pFcb->Header.AllocationSize;
3691     liSaveVDL = pFcb->Header.ValidDataLength;
3692
3693     if( pFcb->Header.FileSize.QuadPart != pBuffer->EndOfFile.QuadPart &&
3694         !pIrpSp->Parameters.SetFile.AdvanceOnly)
3695     {
3696
3697         if( pBuffer->EndOfFile.QuadPart < pFcb->Header.FileSize.QuadPart)
3698         {
3699
3700             AFSDbgTrace(( AFS_SUBSYSTEM_LOCK_PROCESSING|AFS_SUBSYSTEM_SECTION_OBJECT,
3701                           AFS_TRACE_LEVEL_VERBOSE,
3702                           "AFSSetEndOfFileInfo Acquiring Fcb SectionObject lock %p EXCL %08lX\n",
3703                           &pFcb->NPFcb->SectionObjectResource,
3704                           PsGetCurrentThread()));
3705
3706             AFSAcquireExcl( &pFcb->NPFcb->SectionObjectResource,
3707                             TRUE);
3708
3709             __try
3710             {
3711
3712                 bUserMapped = !MmCanFileBeTruncated( pFileObject->SectionObjectPointer,
3713                                                      &pBuffer->EndOfFile);
3714             }
3715             __except( AFSExceptionFilter( __FUNCTION__, GetExceptionCode(), GetExceptionInformation()))
3716             {
3717
3718                 bUserMapped = FALSE;
3719
3720                 ntStatus = GetExceptionCode();
3721
3722                 AFSDbgTrace(( 0,
3723                               0,
3724                               "EXCEPTION - AFSSetEndOfFileInfo MmCanFileBeTruncated failed FID %08lX-%08lX-%08lX-%08lX Status 0x%08lX\n",
3725                               pFcb->ObjectInformation->FileId.Cell,
3726                               pFcb->ObjectInformation->FileId.Volume,
3727                               pFcb->ObjectInformation->FileId.Vnode,
3728                               pFcb->ObjectInformation->FileId.Unique,
3729                               ntStatus));
3730             }
3731
3732             AFSDbgTrace(( AFS_SUBSYSTEM_LOCK_PROCESSING|AFS_SUBSYSTEM_SECTION_OBJECT,
3733                           AFS_TRACE_LEVEL_VERBOSE,
3734                           "AFSSetEndOfFileInfo Releasing Fcb SectionObject lock %p EXCL %08lX\n",
3735                           &pFcb->NPFcb->SectionObjectResource,
3736                           PsGetCurrentThread()));
3737
3738             AFSReleaseResource( &pFcb->NPFcb->SectionObjectResource);
3739
3740             // Truncating the file
3741             if ( bUserMapped)
3742             {
3743
3744                 ntStatus = STATUS_USER_MAPPED_FILE;
3745             }
3746             else
3747             {
3748
3749                 //
3750                 // If this is a truncation we need to grab the paging
3751                 // IO resource.
3752                 //
3753                 AFSDbgTrace(( AFS_SUBSYSTEM_LOCK_PROCESSING,
3754                               AFS_TRACE_LEVEL_VERBOSE,
3755                               "AFSSetEndOfFileInfo Acquiring Fcb PagingIo lock %p EXCL %08lX\n",
3756                               &pFcb->NPFcb->PagingResource,
3757                               PsGetCurrentThread()));
3758
3759                 AFSAcquireExcl( &pFcb->NPFcb->PagingResource,
3760                                 TRUE);
3761
3762                 bReleasePaging = TRUE;
3763
3764                 //
3765                 // Must drop the Fcb Resource.  When changing the file size
3766                 // a deadlock can occur with Trend Micro's filter if the file
3767                 // size is set to zero.
3768                 //
3769
3770                 AFSReleaseResource( &pFcb->NPFcb->Resource);
3771
3772                 pFcb->Header.AllocationSize = pBuffer->EndOfFile;
3773
3774                 pFcb->Header.FileSize = pBuffer->EndOfFile;
3775
3776                 pFcb->ObjectInformation->EndOfFile = pBuffer->EndOfFile;
3777
3778                 pFcb->ObjectInformation->AllocationSize = pBuffer->EndOfFile;
3779
3780                 if( pFcb->Header.ValidDataLength.QuadPart > pFcb->Header.FileSize.QuadPart)
3781                 {
3782
3783                     pFcb->Header.ValidDataLength = pFcb->Header.FileSize;
3784                 }
3785
3786                 bTruncated = TRUE;
3787
3788                 bModified = TRUE;
3789             }
3790         }
3791         else
3792         {
3793
3794             //
3795             // extending the file, move EOF
3796             //
3797
3798             //
3799             // If this is a truncation we need to grab the paging
3800             // IO resource.
3801             //
3802             AFSDbgTrace(( AFS_SUBSYSTEM_LOCK_PROCESSING,
3803                           AFS_TRACE_LEVEL_VERBOSE,
3804                           "AFSSetEndOfFileInfo Acquiring Fcb PagingIo lock %p EXCL %08lX\n",
3805                           &pFcb->NPFcb->PagingResource,
3806                           PsGetCurrentThread()));
3807
3808             AFSAcquireExcl( &pFcb->NPFcb->PagingResource,
3809                             TRUE);
3810
3811             bReleasePaging = TRUE;
3812
3813             //
3814             // Must drop the Fcb Resource.  When changing the file size
3815             // a deadlock can occur with Trend Micro's filter if the file
3816             // size is set to zero.
3817             //
3818
3819             AFSReleaseResource( &pFcb->NPFcb->Resource);
3820
3821             pFcb->Header.FileSize = pBuffer->EndOfFile;
3822
3823             pFcb->ObjectInformation->EndOfFile = pBuffer->EndOfFile;
3824
3825             if (pFcb->Header.FileSize.QuadPart > pFcb->Header.AllocationSize.QuadPart)
3826             {
3827                 //
3828                 // And Allocation as needed.
3829                 //
3830                 pFcb->Header.AllocationSize = pBuffer->EndOfFile;
3831
3832                 pFcb->ObjectInformation->AllocationSize = pBuffer->EndOfFile;
3833             }
3834
3835             bModified = TRUE;
3836         }
3837     }
3838
3839     if (bModified)
3840     {
3841
3842         KeQuerySystemTime( &pFcb->ObjectInformation->ChangeTime);
3843
3844         SetFlag( pFcb->Flags, AFS_FCB_FLAG_FILE_MODIFIED | AFS_FCB_FLAG_UPDATE_CHANGE_TIME);
3845
3846         //
3847         // Tell the server
3848         //
3849
3850         ASSERT( BooleanFlagOn( pFcb->ObjectInformation->Flags, AFS_OBJECT_FLAGS_PARENT_FID));
3851
3852         ntStatus = AFSUpdateFileInformation( &pFcb->ObjectInformation->ParentFileId,
3853                                              pFcb->ObjectInformation,
3854                                              &pCcb->AuthGroup);
3855
3856         if( NT_SUCCESS(ntStatus))
3857         {
3858             //
3859             // We are now good to go so tell CC.
3860             //
3861             CcSetFileSizes( pFileObject,
3862                             (PCC_FILE_SIZES)&pFcb->Header.AllocationSize);
3863
3864             //
3865             // And give up those extents
3866             //
3867             if( bTruncated)
3868             {
3869
3870                 AFSTrimExtents( pFcb,
3871                                 &pFcb->Header.FileSize);
3872             }
3873
3874             //
3875             // Mark the file as modified so as to reflect the change into the last write on close.
3876             //
3877             SetFlag( pFileObject->Flags, FO_FILE_MODIFIED);
3878         }
3879         else
3880         {
3881             pFcb->Header.ValidDataLength = liSaveVDL;
3882             pFcb->Header.FileSize = liSaveSize;
3883             pFcb->Header.AllocationSize = liSaveAlloc;
3884             pFcb->ObjectInformation->EndOfFile = liSaveSize;
3885             pFcb->ObjectInformation->AllocationSize = liSaveAlloc;
3886         }
3887     }
3888
3889     if( bReleasePaging)
3890     {
3891
3892         AFSReleaseResource( &pFcb->NPFcb->PagingResource);
3893
3894         AFSAcquireExcl( &pFcb->NPFcb->Resource,
3895                         TRUE);
3896     }
3897
3898     return ntStatus;
3899 }
3900
3901 NTSTATUS
3902 AFSProcessShareSetInfo( IN IRP *Irp,
3903                         IN AFSFcb *Fcb,
3904                         IN AFSCcb *Ccb)
3905 {
3906
3907     UNREFERENCED_PARAMETER(Fcb);
3908     NTSTATUS ntStatus = STATUS_SUCCESS;
3909     PIO_STACK_LOCATION pIrpSp = IoGetCurrentIrpStackLocation( Irp);
3910     FILE_INFORMATION_CLASS ulFileInformationClass;
3911     void *pPipeInfo = NULL;
3912
3913     __Enter
3914     {
3915         ulFileInformationClass = pIrpSp->Parameters.SetFile.FileInformationClass;
3916
3917         AFSDbgTrace(( AFS_SUBSYSTEM_PIPE_PROCESSING,
3918                       AFS_TRACE_LEVEL_VERBOSE,
3919                       "AFSProcessShareSetInfo On pipe %wZ Class %08lX\n",
3920                       &Ccb->DirectoryCB->NameInformation.FileName,
3921                       ulFileInformationClass));
3922
3923         pPipeInfo = AFSLockSystemBuffer( Irp,
3924                                          pIrpSp->Parameters.SetFile.Length);
3925
3926         if( pPipeInfo == NULL)
3927         {
3928
3929             AFSDbgTrace(( AFS_SUBSYSTEM_PIPE_PROCESSING,
3930                           AFS_TRACE_LEVEL_ERROR,
3931                           "AFSProcessShareSetInfo Failed to lock buffer on pipe %wZ\n",
3932                           &Ccb->DirectoryCB->NameInformation.FileName));
3933
3934             try_return( ntStatus = STATUS_INSUFFICIENT_RESOURCES);
3935         }
3936
3937         //
3938         // Send the request to the service
3939         //
3940
3941         ntStatus = AFSNotifySetPipeInfo( Ccb,
3942                                          (ULONG)ulFileInformationClass,
3943                                          pIrpSp->Parameters.SetFile.Length,
3944                                          pPipeInfo);
3945
3946         if( !NT_SUCCESS( ntStatus))
3947         {
3948
3949             AFSDbgTrace(( AFS_SUBSYSTEM_PIPE_PROCESSING,
3950                           AFS_TRACE_LEVEL_ERROR,
3951                           "AFSProcessShareSetInfo Failed to send request to service on pipe %wZ Status %08lX\n",
3952                           &Ccb->DirectoryCB->NameInformation.FileName,
3953                           ntStatus));
3954
3955             try_return( ntStatus);
3956         }
3957
3958         AFSDbgTrace(( AFS_SUBSYSTEM_PIPE_PROCESSING,
3959                       AFS_TRACE_LEVEL_VERBOSE,
3960                       "AFSProcessShareSetInfo Completed request on pipe %wZ Class %08lX\n",
3961                       &Ccb->DirectoryCB->NameInformation.FileName,
3962                       ulFileInformationClass));
3963
3964 try_exit:
3965
3966         NOTHING;
3967     }
3968
3969     return ntStatus;
3970 }
3971
3972 NTSTATUS
3973 AFSProcessShareQueryInfo( IN IRP *Irp,
3974                           IN AFSFcb *Fcb,
3975                           IN AFSCcb *Ccb)
3976 {
3977
3978     UNREFERENCED_PARAMETER(Fcb);
3979     NTSTATUS ntStatus = STATUS_SUCCESS;
3980     PIO_STACK_LOCATION pIrpSp = IoGetCurrentIrpStackLocation( Irp);
3981     FILE_INFORMATION_CLASS ulFileInformationClass;
3982     void *pPipeInfo = NULL;
3983
3984     __Enter
3985     {
3986
3987         ulFileInformationClass = pIrpSp->Parameters.QueryFile.FileInformationClass;
3988
3989         AFSDbgTrace(( AFS_SUBSYSTEM_PIPE_PROCESSING,
3990                       AFS_TRACE_LEVEL_VERBOSE,
3991                       "AFSProcessShareQueryInfo On pipe %wZ Class %08lX\n",
3992                       &Ccb->DirectoryCB->NameInformation.FileName,
3993                       ulFileInformationClass));
3994
3995         pPipeInfo = AFSLockSystemBuffer( Irp,
3996                                          pIrpSp->Parameters.QueryFile.Length);
3997
3998         if( pPipeInfo == NULL)
3999         {
4000
4001             AFSDbgTrace(( AFS_SUBSYSTEM_PIPE_PROCESSING,
4002                           AFS_TRACE_LEVEL_ERROR,
4003                           "AFSProcessShareQueryInfo Failed to lock buffer on pipe %wZ\n",
4004                           &Ccb->DirectoryCB->NameInformation.FileName));
4005
4006             try_return( ntStatus = STATUS_INSUFFICIENT_RESOURCES);
4007         }
4008
4009         //
4010         // Send the request to the service
4011         //
4012
4013         ntStatus = AFSNotifyQueryPipeInfo( Ccb,
4014                                            (ULONG)ulFileInformationClass,
4015                                            pIrpSp->Parameters.QueryFile.Length,
4016                                            pPipeInfo,
4017                                            (ULONG *)&Irp->IoStatus.Information);
4018
4019         if( !NT_SUCCESS( ntStatus))
4020         {
4021
4022             AFSDbgTrace(( AFS_SUBSYSTEM_PIPE_PROCESSING,
4023                           AFS_TRACE_LEVEL_ERROR,
4024                           "AFSProcessShareQueryInfo Failed to send request to service on pipe %wZ Status %08lX\n",
4025                           &Ccb->DirectoryCB->NameInformation.FileName,
4026                           ntStatus));
4027
4028             try_return( ntStatus);
4029         }
4030
4031         AFSDbgTrace(( AFS_SUBSYSTEM_PIPE_PROCESSING,
4032                       AFS_TRACE_LEVEL_VERBOSE,
4033                       "AFSProcessShareQueryInfo Completed request on pipe %wZ Class %08lX\n",
4034                       &Ccb->DirectoryCB->NameInformation.FileName,
4035                       ulFileInformationClass));
4036
4037 try_exit:
4038
4039         NOTHING;
4040     }
4041
4042     return ntStatus;
4043 }
4044
4045 NTSTATUS
4046 AFSProcessPIOCtlQueryInfo( IN IRP *Irp,
4047                            IN AFSFcb *Fcb,
4048                            IN AFSCcb *Ccb,
4049                            IN OUT LONG *Length)
4050 {
4051
4052     UNREFERENCED_PARAMETER(Fcb);
4053     UNREFERENCED_PARAMETER(Ccb);
4054     NTSTATUS ntStatus = STATUS_SUCCESS;
4055     PIO_STACK_LOCATION pIrpSp = IoGetCurrentIrpStackLocation( Irp);
4056     FILE_INFORMATION_CLASS ulFileInformationClass;
4057
4058     __Enter
4059     {
4060
4061         ulFileInformationClass = pIrpSp->Parameters.QueryFile.FileInformationClass;
4062
4063         switch( ulFileInformationClass)
4064         {
4065
4066             case FileBasicInformation:
4067             {
4068
4069                 AFSDbgTrace(( AFS_SUBSYSTEM_PIOCTL_PROCESSING,
4070                               AFS_TRACE_LEVEL_VERBOSE,
4071                               "AFSProcessPIOCtlQueryInfo (FileBasicInformation)\n"));
4072
4073                 if ( *Length >= sizeof( FILE_BASIC_INFORMATION))
4074                 {
4075                     PFILE_BASIC_INFORMATION pBasic = (PFILE_BASIC_INFORMATION)Irp->AssociatedIrp.SystemBuffer;
4076
4077                     pBasic->CreationTime.QuadPart = 0;
4078                     pBasic->LastAccessTime.QuadPart = 0;
4079                     pBasic->ChangeTime.QuadPart = 0;
4080                     pBasic->LastWriteTime.QuadPart = 0;
4081                     pBasic->FileAttributes = FILE_ATTRIBUTE_HIDDEN | FILE_ATTRIBUTE_SYSTEM;
4082
4083                     *Length -= sizeof( FILE_BASIC_INFORMATION);
4084                 }
4085                 else
4086                 {
4087                     ntStatus = STATUS_BUFFER_TOO_SMALL;
4088                 }
4089
4090                 break;
4091             }
4092
4093             case FileStandardInformation:
4094             {
4095
4096                 AFSDbgTrace(( AFS_SUBSYSTEM_PIOCTL_PROCESSING,
4097                               AFS_TRACE_LEVEL_VERBOSE,
4098                               "AFSProcessPIOCtlQueryInfo (FileStandardInformation)\n"));
4099
4100                 if ( *Length >= sizeof( FILE_STANDARD_INFORMATION))
4101                 {
4102                     PFILE_STANDARD_INFORMATION pStandard = (PFILE_STANDARD_INFORMATION)Irp->AssociatedIrp.SystemBuffer;
4103
4104                     pStandard->NumberOfLinks = 1;
4105                     pStandard->DeletePending = 0;
4106                     pStandard->AllocationSize.QuadPart = 0;
4107                     pStandard->EndOfFile.QuadPart = 0;
4108                     pStandard->Directory = 0;
4109
4110                     *Length -= sizeof( FILE_STANDARD_INFORMATION);
4111                 }
4112                 else
4113                 {
4114                     ntStatus = STATUS_BUFFER_TOO_SMALL;
4115                 }
4116
4117                 break;
4118             }
4119
4120             case FileNormalizedNameInformation:
4121             case FileNameInformation:
4122             {
4123
4124                 ULONG ulCopyLength = 0;
4125                 AFSFcb *pFcb = NULL;
4126                 AFSCcb *pCcb = NULL;
4127                 USHORT usFullNameLength = 0;
4128                 PFILE_NAME_INFORMATION pNameInfo = (PFILE_NAME_INFORMATION)Irp->AssociatedIrp.SystemBuffer;
4129                 UNICODE_STRING uniName;
4130
4131                 AFSDbgTrace(( AFS_SUBSYSTEM_PIOCTL_PROCESSING,
4132                               AFS_TRACE_LEVEL_VERBOSE,
4133                               "AFSProcessPIOCtlQueryInfo (FileNameInformation)\n"));
4134
4135                 pFcb = (AFSFcb *)pIrpSp->FileObject->FsContext;
4136                 pCcb = (AFSCcb *)pIrpSp->FileObject->FsContext2;
4137
4138                 if( *Length < FIELD_OFFSET( FILE_NAME_INFORMATION, FileName))
4139                 {
4140                     ntStatus = STATUS_BUFFER_TOO_SMALL;
4141                     break;
4142                 }
4143
4144                 RtlZeroMemory( pNameInfo,
4145                                *Length);
4146
4147                 usFullNameLength = sizeof( WCHAR) +
4148                                             AFSServerName.Length +
4149                                             pCcb->FullFileName.Length;
4150
4151                 if( *Length >= (LONG)(FIELD_OFFSET( FILE_NAME_INFORMATION, FileName) + (LONG)usFullNameLength))
4152                 {
4153                     ulCopyLength = (LONG)usFullNameLength;
4154                 }
4155                 else
4156                 {
4157                     ulCopyLength = *Length - FIELD_OFFSET( FILE_NAME_INFORMATION, FileName);
4158                     ntStatus = STATUS_BUFFER_OVERFLOW;
4159                 }
4160
4161                 pNameInfo->FileNameLength = (ULONG)usFullNameLength;
4162
4163                 *Length -= FIELD_OFFSET( FILE_NAME_INFORMATION, FileName);
4164
4165                 if( ulCopyLength > 0)
4166                 {
4167
4168                     pNameInfo->FileName[ 0] = L'\\';
4169                     ulCopyLength -= sizeof( WCHAR);
4170
4171                     *Length -= sizeof( WCHAR);
4172
4173                     if( ulCopyLength >= AFSServerName.Length)
4174                     {
4175
4176                         RtlCopyMemory( &pNameInfo->FileName[ 1],
4177                                        AFSServerName.Buffer,
4178                                        AFSServerName.Length);
4179
4180                         ulCopyLength -= AFSServerName.Length;
4181                         *Length -= AFSServerName.Length;
4182
4183                         if( ulCopyLength >= pCcb->FullFileName.Length)
4184                         {
4185
4186                             RtlCopyMemory( &pNameInfo->FileName[ 1 + (AFSServerName.Length/sizeof( WCHAR))],
4187                                            pCcb->FullFileName.Buffer,
4188                                            pCcb->FullFileName.Length);
4189
4190                             ulCopyLength -= pCcb->FullFileName.Length;
4191                             *Length -= pCcb->FullFileName.Length;
4192
4193                             uniName.Length = (USHORT)pNameInfo->FileNameLength;
4194                             uniName.MaximumLength = uniName.Length;
4195                             uniName.Buffer = pNameInfo->FileName;
4196                         }
4197                         else
4198                         {
4199
4200                             RtlCopyMemory( &pNameInfo->FileName[ 1 + (AFSServerName.Length/sizeof( WCHAR))],
4201                                            pCcb->FullFileName.Buffer,
4202                                            ulCopyLength);
4203
4204                             *Length -= ulCopyLength;
4205
4206                             uniName.Length = (USHORT)(sizeof( WCHAR) + AFSServerName.Length + ulCopyLength);
4207                             uniName.MaximumLength = uniName.Length;
4208                             uniName.Buffer = pNameInfo->FileName;
4209                         }
4210
4211                         AFSDbgTrace(( AFS_SUBSYSTEM_PIOCTL_PROCESSING,
4212                                       AFS_TRACE_LEVEL_VERBOSE,
4213                                       "AFSProcessPIOCtlQueryInfo (FileNameInformation) Returning %wZ\n",
4214                                       &uniName));
4215                     }
4216                 }
4217
4218                 break;
4219             }
4220
4221             case FileInternalInformation:
4222             {
4223
4224                 PFILE_INTERNAL_INFORMATION pInternalInfo = (PFILE_INTERNAL_INFORMATION)Irp->AssociatedIrp.SystemBuffer;
4225
4226                 AFSDbgTrace(( AFS_SUBSYSTEM_PIOCTL_PROCESSING,
4227                               AFS_TRACE_LEVEL_VERBOSE,
4228                               "AFSProcessPIOCtlQueryInfo (FileInternalInformation)\n"));
4229
4230                 if( *Length >= sizeof( FILE_INTERNAL_INFORMATION))
4231                 {
4232
4233                     pInternalInfo->IndexNumber.HighPart = 0;
4234
4235                     pInternalInfo->IndexNumber.LowPart = 0;
4236
4237                     *Length -= sizeof( FILE_INTERNAL_INFORMATION);
4238                 }
4239                 else
4240                 {
4241
4242                     ntStatus = STATUS_BUFFER_TOO_SMALL;
4243                 }
4244
4245                 break;
4246             }
4247
4248             case FileAllInformation:
4249             {
4250                 ntStatus = STATUS_INVALID_PARAMETER;
4251
4252                 AFSDbgTrace(( AFS_SUBSYSTEM_PIOCTL_PROCESSING,
4253                               AFS_TRACE_LEVEL_WARNING,
4254                               "AFSProcessPIOCtlQueryInfo (FileAllInformation) Not Implemented\n"));
4255
4256                 break;
4257             }
4258
4259             case FileEaInformation:
4260             {
4261                 ntStatus = STATUS_INVALID_PARAMETER;
4262
4263                 AFSDbgTrace(( AFS_SUBSYSTEM_PIOCTL_PROCESSING,
4264                               AFS_TRACE_LEVEL_WARNING,
4265                               "AFSProcessPIOCtlQueryInfo (FileEaInformation) Not Implemented\n"));
4266
4267                 break;
4268             }
4269
4270             case FilePositionInformation:
4271             {
4272                 ntStatus = STATUS_INVALID_PARAMETER;
4273
4274                 AFSDbgTrace(( AFS_SUBSYSTEM_PIOCTL_PROCESSING,
4275                               AFS_TRACE_LEVEL_WARNING,
4276                               "AFSProcessPIOCtlQueryInfo (FilePositionInformation) Not Implemented\n"));
4277
4278                 break;
4279             }
4280
4281             case FileAlternateNameInformation:
4282             {
4283                 ntStatus = STATUS_INVALID_PARAMETER;
4284
4285                 AFSDbgTrace(( AFS_SUBSYSTEM_PIOCTL_PROCESSING,
4286                               AFS_TRACE_LEVEL_WARNING,
4287                               "AFSProcessPIOCtlQueryInfo (FileAlternateNameInformation) Not Implemented\n"));
4288
4289                 break;
4290             }
4291
4292             case FileNetworkOpenInformation:
4293             {
4294                 ntStatus = STATUS_INVALID_PARAMETER;
4295
4296                 AFSDbgTrace(( AFS_SUBSYSTEM_PIOCTL_PROCESSING,
4297                               AFS_TRACE_LEVEL_WARNING,
4298                               "AFSProcessPIOCtlQueryInfo (FileNetworkOpenInformation) Not Implemented\n"));
4299
4300                 break;
4301             }
4302
4303             case FileStreamInformation:
4304             {
4305                 ntStatus = STATUS_INVALID_PARAMETER;
4306
4307                 AFSDbgTrace(( AFS_SUBSYSTEM_PIOCTL_PROCESSING,
4308                               AFS_TRACE_LEVEL_WARNING,
4309                               "AFSProcessPIOCtlQueryInfo (FileStreamInformation) Not Implemented\n"));
4310
4311                 break;
4312             }
4313
4314             case FileAttributeTagInformation:
4315             {
4316                 ntStatus = STATUS_INVALID_PARAMETER;
4317
4318                 AFSDbgTrace(( AFS_SUBSYSTEM_PIOCTL_PROCESSING,
4319                               AFS_TRACE_LEVEL_WARNING,
4320                               "AFSProcessPIOCtlQueryInfo (FileAttributeTagInformation) Not Implemented\n"));
4321
4322                 break;
4323             }
4324
4325             case FileRemoteProtocolInformation:
4326             {
4327                 ntStatus = STATUS_INVALID_PARAMETER;
4328
4329                 AFSDbgTrace(( AFS_SUBSYSTEM_PIOCTL_PROCESSING,
4330                               AFS_TRACE_LEVEL_WARNING,
4331                               "AFSProcessPIOCtlQueryInfo (FileRemoteProtocolInformation) Not Implemented\n"));
4332
4333                 break;
4334             }
4335
4336             case FileNetworkPhysicalNameInformation:
4337             {
4338                 ntStatus = STATUS_INVALID_PARAMETER;
4339
4340                 AFSDbgTrace(( AFS_SUBSYSTEM_PIOCTL_PROCESSING,
4341                               AFS_TRACE_LEVEL_WARNING,
4342                               "AFSProcessPIOCtlQueryInfo (FileNetworkPhysicalNameInformation) Not Implemented\n"));
4343
4344                 break;
4345             }
4346
4347             default:
4348             {
4349                 ntStatus = STATUS_INVALID_PARAMETER;
4350
4351                 AFSDbgTrace(( AFS_SUBSYSTEM_PIOCTL_PROCESSING,
4352                               AFS_TRACE_LEVEL_WARNING,
4353                               "AFSProcessPIOCtlQueryInfo Not handling request %08lX\n",
4354                               ulFileInformationClass));
4355
4356                 break;
4357             }
4358         }
4359     }
4360
4361     AFSDbgTrace(( AFS_SUBSYSTEM_PIOCTL_PROCESSING,
4362                   AFS_TRACE_LEVEL_VERBOSE,
4363                   "AFSProcessPIOCtlQueryInfo ntStatus %08lX\n",
4364                   ntStatus));
4365
4366     return ntStatus;
4367 }
4368