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