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