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