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