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