965950558ecf24cd130bd5c3d90e5c1b90aef195
[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                 ulFileAttribs |= FILE_ATTRIBUTE_REPARSE_POINT;
785             }
786         }
787
788         Buffer->CreationTime = DirectoryCB->ObjectInformation->CreationTime;
789         Buffer->LastAccessTime = DirectoryCB->ObjectInformation->LastAccessTime;
790         Buffer->LastWriteTime = DirectoryCB->ObjectInformation->LastWriteTime;
791         Buffer->ChangeTime = DirectoryCB->ObjectInformation->ChangeTime;
792         Buffer->FileAttributes = ulFileAttribs;
793
794         if( DirectoryCB->NameInformation.FileName.Buffer[ 0] == L'.' &&
795             BooleanFlagOn( pDeviceExt->DeviceFlags, AFS_DEVICE_FLAG_HIDE_DOT_NAMES))
796         {
797
798             if ( Buffer->FileAttributes != FILE_ATTRIBUTE_NORMAL)
799             {
800                 Buffer->FileAttributes |= FILE_ATTRIBUTE_HIDDEN;
801             }
802             else
803             {
804                 Buffer->FileAttributes = FILE_ATTRIBUTE_HIDDEN;
805             }
806         }
807
808         *Length -= sizeof( FILE_BASIC_INFORMATION);
809     }
810     else
811     {
812
813         ntStatus = STATUS_BUFFER_TOO_SMALL;
814     }
815
816     return ntStatus;
817 }
818
819 NTSTATUS
820 AFSQueryStandardInfo( IN PIRP Irp,
821                       IN AFSDirectoryCB *DirectoryCB,
822                       IN OUT PFILE_STANDARD_INFORMATION Buffer,
823                       IN OUT PLONG Length)
824 {
825
826     NTSTATUS ntStatus = STATUS_SUCCESS;
827     AFSCcb *pCcb = NULL;
828     PIO_STACK_LOCATION pIrpSp = IoGetCurrentIrpStackLocation( Irp);
829     AFSFileInfoCB stFileInfo;
830     AFSDirectoryCB *pParentDirectoryCB = NULL;
831     UNICODE_STRING uniParentPath;
832     ULONG ulFileAttribs = 0;
833
834     if( *Length >= sizeof( FILE_STANDARD_INFORMATION))
835     {
836
837         pCcb = (AFSCcb *)pIrpSp->FileObject->FsContext2;
838
839         RtlZeroMemory( Buffer,
840                        *Length);
841
842         Buffer->NumberOfLinks = 1;
843         Buffer->DeletePending = BooleanFlagOn( pCcb->DirectoryCB->Flags, AFS_DIR_ENTRY_PENDING_DELETE);
844
845         Buffer->AllocationSize.QuadPart = (ULONGLONG)((DirectoryCB->ObjectInformation->AllocationSize.QuadPart/PAGE_SIZE) + 1) * PAGE_SIZE;
846
847         Buffer->EndOfFile = DirectoryCB->ObjectInformation->EndOfFile;
848
849         ulFileAttribs = DirectoryCB->ObjectInformation->FileAttributes;
850
851         if( DirectoryCB->ObjectInformation->FileType == AFS_FILE_TYPE_SYMLINK)
852         {
853
854             pCcb = (AFSCcb *)pIrpSp->FileObject->FsContext2;
855
856             pParentDirectoryCB = AFSGetParentEntry( pCcb->NameArray);
857
858             AFSRetrieveParentPath( &pCcb->FullFileName,
859                                    &uniParentPath);
860
861             RtlZeroMemory( &stFileInfo,
862                            sizeof( AFSFileInfoCB));
863
864             if( NT_SUCCESS( AFSRetrieveFileAttributes( pParentDirectoryCB,
865                                                        DirectoryCB,
866                                                        &uniParentPath,
867                                                        NULL,
868                                                        &stFileInfo)))
869             {
870                 ulFileAttribs = stFileInfo.FileAttributes;
871             }
872         }
873
874         Buffer->Directory = BooleanFlagOn( ulFileAttribs, FILE_ATTRIBUTE_DIRECTORY);
875
876         *Length -= sizeof( FILE_STANDARD_INFORMATION);
877     }
878     else
879     {
880
881         ntStatus = STATUS_BUFFER_TOO_SMALL;
882     }
883
884     return ntStatus;
885 }
886
887 NTSTATUS
888 AFSQueryInternalInfo( IN PIRP Irp,
889                       IN AFSFcb *Fcb,
890                       IN OUT PFILE_INTERNAL_INFORMATION Buffer,
891                       IN OUT PLONG Length)
892 {
893
894     NTSTATUS ntStatus = STATUS_SUCCESS;
895
896     if( *Length >= sizeof( FILE_INTERNAL_INFORMATION))
897     {
898
899         Buffer->IndexNumber.HighPart = Fcb->ObjectInformation->FileId.Volume;
900
901         Buffer->IndexNumber.LowPart = Fcb->ObjectInformation->FileId.Vnode;
902
903         *Length -= sizeof( FILE_INTERNAL_INFORMATION);
904     }
905     else
906     {
907
908         ntStatus = STATUS_BUFFER_TOO_SMALL;
909     }
910
911     return ntStatus;
912 }
913
914 NTSTATUS
915 AFSQueryEaInfo( IN PIRP Irp,
916                 IN AFSDirectoryCB *DirectoryCB,
917                 IN OUT PFILE_EA_INFORMATION Buffer,
918                 IN OUT PLONG Length)
919 {
920
921     NTSTATUS ntStatus = STATUS_SUCCESS;
922
923     RtlZeroMemory( Buffer,
924                    *Length);
925
926     if( *Length >= sizeof( FILE_EA_INFORMATION))
927     {
928
929         Buffer->EaSize = 0;
930
931         *Length -= sizeof( FILE_EA_INFORMATION);
932     }
933     else
934     {
935
936         ntStatus = STATUS_BUFFER_TOO_SMALL;
937     }
938
939     return ntStatus;
940 }
941
942 NTSTATUS
943 AFSQueryPositionInfo( IN PIRP Irp,
944                       IN AFSFcb *Fcb,
945                       IN OUT PFILE_POSITION_INFORMATION Buffer,
946                       IN OUT PLONG Length)
947 {
948
949     NTSTATUS ntStatus = STATUS_SUCCESS;
950     PIO_STACK_LOCATION pIrpSp = IoGetCurrentIrpStackLocation( Irp);
951
952     if( *Length >= sizeof( FILE_POSITION_INFORMATION))
953     {
954
955         RtlZeroMemory( Buffer,
956                        *Length);
957
958         Buffer->CurrentByteOffset.QuadPart = pIrpSp->FileObject->CurrentByteOffset.QuadPart;
959
960         *Length -= sizeof( FILE_POSITION_INFORMATION);
961     }
962     else
963     {
964
965         ntStatus = STATUS_BUFFER_TOO_SMALL;
966     }
967
968     return ntStatus;
969 }
970
971 NTSTATUS
972 AFSQueryAccess( IN PIRP Irp,
973                 IN AFSFcb *Fcb,
974                 IN OUT PFILE_ACCESS_INFORMATION Buffer,
975                 IN OUT PLONG Length)
976 {
977
978     NTSTATUS ntStatus = STATUS_SUCCESS;
979
980     if( *Length >= sizeof( FILE_ACCESS_INFORMATION))
981     {
982
983         RtlZeroMemory( Buffer,
984                        *Length);
985
986         Buffer->AccessFlags = 0;
987
988         *Length -= sizeof( FILE_ACCESS_INFORMATION);
989     }
990     else
991     {
992
993         ntStatus = STATUS_BUFFER_TOO_SMALL;
994     }
995
996     return ntStatus;
997 }
998
999 NTSTATUS
1000 AFSQueryMode( IN PIRP Irp,
1001               IN AFSFcb *Fcb,
1002               IN OUT PFILE_MODE_INFORMATION Buffer,
1003               IN OUT PLONG Length)
1004 {
1005
1006     NTSTATUS ntStatus = STATUS_SUCCESS;
1007
1008     if( *Length >= sizeof( FILE_MODE_INFORMATION))
1009     {
1010
1011         RtlZeroMemory( Buffer,
1012                        *Length);
1013
1014         Buffer->Mode = 0;
1015
1016         *Length -= sizeof( FILE_MODE_INFORMATION);
1017     }
1018     else
1019     {
1020
1021         ntStatus = STATUS_BUFFER_TOO_SMALL;
1022     }
1023
1024     return ntStatus;
1025 }
1026
1027 NTSTATUS
1028 AFSQueryAlignment( IN PIRP Irp,
1029                    IN AFSFcb *Fcb,
1030                    IN OUT PFILE_ALIGNMENT_INFORMATION Buffer,
1031                    IN OUT PLONG Length)
1032 {
1033
1034     NTSTATUS ntStatus = STATUS_SUCCESS;
1035
1036     if( *Length >= sizeof( FILE_ALIGNMENT_INFORMATION))
1037     {
1038
1039         RtlZeroMemory( Buffer,
1040                        *Length);
1041
1042         Buffer->AlignmentRequirement = 1;
1043
1044         *Length -= sizeof( FILE_ALIGNMENT_INFORMATION);
1045     }
1046     else
1047     {
1048
1049         ntStatus = STATUS_BUFFER_TOO_SMALL;
1050     }
1051
1052     return ntStatus;
1053 }
1054
1055 NTSTATUS
1056 AFSQueryNameInfo( IN PIRP Irp,
1057                   IN AFSDirectoryCB *DirectoryCB,
1058                   IN OUT PFILE_NAME_INFORMATION Buffer,
1059                   IN OUT PLONG Length)
1060 {
1061
1062     NTSTATUS ntStatus = STATUS_SUCCESS;
1063     ULONG ulCopyLength = 0;
1064     ULONG cchCopied = 0;
1065     AFSFcb *pFcb = NULL;
1066     AFSCcb *pCcb = NULL;
1067     IO_STACK_LOCATION *pIrpSp = IoGetCurrentIrpStackLocation( Irp);
1068     BOOLEAN bAddLeadingSlash = FALSE;
1069     BOOLEAN bAddTrailingSlash = FALSE;
1070     USHORT usFullNameLength = 0;
1071
1072     pFcb = (AFSFcb *)pIrpSp->FileObject->FsContext;
1073
1074     pCcb = (AFSCcb *)pIrpSp->FileObject->FsContext2;
1075
1076     if( *Length >= FIELD_OFFSET( FILE_NAME_INFORMATION, FileName))
1077     {
1078
1079         RtlZeroMemory( Buffer,
1080                        *Length);
1081
1082         if( pCcb->FullFileName.Length == 0 ||
1083             pCcb->FullFileName.Buffer[ 0] != L'\\')
1084         {
1085             bAddLeadingSlash = TRUE;
1086         }
1087
1088         if( pFcb->ObjectInformation->FileType == AFS_FILE_TYPE_DIRECTORY &&
1089             pCcb->FullFileName.Length > 0 &&
1090             pCcb->FullFileName.Buffer[ (pCcb->FullFileName.Length/sizeof( WCHAR)) - 1] != L'\\')
1091         {
1092             bAddTrailingSlash = TRUE;
1093         }
1094
1095         usFullNameLength = sizeof( WCHAR) +
1096                                     AFSServerName.Length +
1097                                     pCcb->FullFileName.Length;
1098
1099         if( bAddLeadingSlash)
1100         {
1101             usFullNameLength += sizeof( WCHAR);
1102         }
1103
1104         if( bAddTrailingSlash)
1105         {
1106             usFullNameLength += sizeof( WCHAR);
1107         }
1108
1109         if( *Length >= (LONG)(FIELD_OFFSET( FILE_NAME_INFORMATION, FileName) + (LONG)usFullNameLength))
1110         {
1111
1112             ulCopyLength = (LONG)usFullNameLength;
1113         }
1114         else
1115         {
1116
1117             ulCopyLength = *Length - FIELD_OFFSET( FILE_NAME_INFORMATION, FileName);
1118
1119             ntStatus = STATUS_BUFFER_OVERFLOW;
1120         }
1121
1122         Buffer->FileNameLength = (ULONG)usFullNameLength;
1123
1124         *Length -= FIELD_OFFSET( FILE_NAME_INFORMATION, FileName);
1125
1126         if( ulCopyLength > 0)
1127         {
1128
1129             Buffer->FileName[ 0] = L'\\';
1130             ulCopyLength -= sizeof( WCHAR);
1131
1132             *Length -= sizeof( WCHAR);
1133             cchCopied += 1;
1134
1135             if( ulCopyLength >= AFSServerName.Length)
1136             {
1137
1138                 RtlCopyMemory( &Buffer->FileName[ 1],
1139                                AFSServerName.Buffer,
1140                                AFSServerName.Length);
1141
1142                 ulCopyLength -= AFSServerName.Length;
1143                 *Length -= AFSServerName.Length;
1144                 cchCopied += AFSServerName.Length/sizeof( WCHAR);
1145
1146                 if ( ulCopyLength > 0 &&
1147                      bAddLeadingSlash)
1148                 {
1149
1150                     Buffer->FileName[ cchCopied] = L'\\';
1151
1152                     ulCopyLength -= sizeof( WCHAR);
1153                     *Length -= sizeof( WCHAR);
1154                     cchCopied++;
1155                 }
1156
1157                 if( ulCopyLength >= pCcb->FullFileName.Length)
1158                 {
1159
1160                     RtlCopyMemory( &Buffer->FileName[ cchCopied],
1161                                    pCcb->FullFileName.Buffer,
1162                                    pCcb->FullFileName.Length);
1163
1164                     ulCopyLength -= pCcb->FullFileName.Length;
1165                     *Length -= pCcb->FullFileName.Length;
1166                     cchCopied += pCcb->FullFileName.Length/sizeof( WCHAR);
1167
1168                     if( ulCopyLength > 0 &&
1169                         bAddTrailingSlash)
1170                     {
1171                         Buffer->FileName[ cchCopied] = L'\\';
1172
1173                         *Length -= sizeof( WCHAR);
1174                     }
1175                 }
1176                 else
1177                 {
1178
1179                     RtlCopyMemory( &Buffer->FileName[ cchCopied],
1180                                    pCcb->FullFileName.Buffer,
1181                                    ulCopyLength);
1182
1183                     *Length -= ulCopyLength;
1184                 }
1185             }
1186         }
1187     }
1188     else
1189     {
1190
1191         ntStatus = STATUS_BUFFER_TOO_SMALL;
1192     }
1193
1194     return ntStatus;
1195 }
1196
1197 NTSTATUS
1198 AFSQueryShortNameInfo( IN PIRP Irp,
1199                        IN AFSDirectoryCB *DirectoryCB,
1200                        IN OUT PFILE_NAME_INFORMATION Buffer,
1201                        IN OUT PLONG Length)
1202 {
1203
1204     NTSTATUS ntStatus = STATUS_BUFFER_TOO_SMALL;
1205     ULONG ulCopyLength = 0;
1206
1207     RtlZeroMemory( Buffer,
1208                    *Length);
1209
1210     if( DirectoryCB->NameInformation.ShortNameLength == 0)
1211     {
1212
1213         //
1214         // The short name IS the long name
1215         //
1216
1217         if( *Length >= (LONG)FIELD_OFFSET( FILE_NAME_INFORMATION, FileName))
1218         {
1219
1220             if( *Length >= (LONG)(FIELD_OFFSET( FILE_NAME_INFORMATION, FileName) + (LONG)DirectoryCB->NameInformation.FileName.Length))
1221             {
1222
1223                 ulCopyLength = (LONG)DirectoryCB->NameInformation.FileName.Length;
1224
1225                 ntStatus = STATUS_SUCCESS;
1226             }
1227             else
1228             {
1229
1230                 ulCopyLength = *Length - FIELD_OFFSET( FILE_NAME_INFORMATION, FileName);
1231
1232                 ntStatus = STATUS_BUFFER_OVERFLOW;
1233             }
1234
1235             Buffer->FileNameLength = DirectoryCB->NameInformation.FileName.Length;
1236
1237             *Length -= FIELD_OFFSET( FILE_NAME_INFORMATION, FileName);
1238
1239             if( ulCopyLength > 0)
1240             {
1241
1242                 RtlCopyMemory( Buffer->FileName,
1243                                DirectoryCB->NameInformation.FileName.Buffer,
1244                                ulCopyLength);
1245
1246                 *Length -= ulCopyLength;
1247             }
1248         }
1249     }
1250     else
1251     {
1252
1253         if( *Length >= (LONG)FIELD_OFFSET( FILE_NAME_INFORMATION, FileName))
1254         {
1255
1256             if( *Length >= (LONG)(FIELD_OFFSET( FILE_NAME_INFORMATION, FileName) + (LONG)DirectoryCB->NameInformation.FileName.Length))
1257             {
1258
1259                 ulCopyLength = (LONG)DirectoryCB->NameInformation.ShortNameLength;
1260
1261                 ntStatus = STATUS_SUCCESS;
1262             }
1263             else
1264             {
1265
1266                 ulCopyLength = *Length - FIELD_OFFSET( FILE_NAME_INFORMATION, FileName);
1267
1268                 ntStatus = STATUS_BUFFER_OVERFLOW;
1269             }
1270
1271             Buffer->FileNameLength = DirectoryCB->NameInformation.ShortNameLength;
1272
1273             *Length -= FIELD_OFFSET( FILE_NAME_INFORMATION, FileName);
1274
1275             if( ulCopyLength > 0)
1276             {
1277
1278                 RtlCopyMemory( Buffer->FileName,
1279                                DirectoryCB->NameInformation.ShortName,
1280                                Buffer->FileNameLength);
1281
1282                 *Length -= ulCopyLength;
1283             }
1284         }
1285     }
1286
1287     return ntStatus;
1288 }
1289
1290 NTSTATUS
1291 AFSQueryNetworkInfo( IN PIRP Irp,
1292                      IN AFSDirectoryCB *DirectoryCB,
1293                      IN OUT PFILE_NETWORK_OPEN_INFORMATION Buffer,
1294                      IN OUT PLONG Length)
1295 {
1296
1297     NTSTATUS ntStatus = STATUS_SUCCESS;
1298     AFSDeviceExt *pDeviceExt = (AFSDeviceExt *)AFSRDRDeviceObject->DeviceExtension;
1299     AFSCcb *pCcb = NULL;
1300     PIO_STACK_LOCATION pIrpSp = IoGetCurrentIrpStackLocation( Irp);
1301     AFSFileInfoCB stFileInfo;
1302     AFSDirectoryCB *pParentDirectoryCB = NULL;
1303     UNICODE_STRING uniParentPath;
1304     ULONG ulFileAttribs = 0;
1305
1306     RtlZeroMemory( Buffer,
1307                    *Length);
1308
1309     if( *Length >= sizeof( FILE_NETWORK_OPEN_INFORMATION))
1310     {
1311
1312         ulFileAttribs = DirectoryCB->ObjectInformation->FileAttributes;
1313
1314         if( DirectoryCB->ObjectInformation->FileType == AFS_FILE_TYPE_SYMLINK)
1315         {
1316
1317             pCcb = (AFSCcb *)pIrpSp->FileObject->FsContext2;
1318
1319             pParentDirectoryCB = AFSGetParentEntry( pCcb->NameArray);
1320
1321             AFSRetrieveParentPath( &pCcb->FullFileName,
1322                                    &uniParentPath);
1323
1324             RtlZeroMemory( &stFileInfo,
1325                            sizeof( AFSFileInfoCB));
1326
1327             if( NT_SUCCESS( AFSRetrieveFileAttributes( pParentDirectoryCB,
1328                                                        DirectoryCB,
1329                                                        &uniParentPath,
1330                                                        NULL,
1331                                                        &stFileInfo)))
1332             {
1333                 ulFileAttribs = stFileInfo.FileAttributes;
1334
1335                 ulFileAttribs |= FILE_ATTRIBUTE_REPARSE_POINT;
1336             }
1337         }
1338
1339         Buffer->CreationTime.QuadPart = DirectoryCB->ObjectInformation->CreationTime.QuadPart;
1340         Buffer->LastAccessTime.QuadPart = DirectoryCB->ObjectInformation->LastAccessTime.QuadPart;
1341         Buffer->LastWriteTime.QuadPart = DirectoryCB->ObjectInformation->LastWriteTime.QuadPart;
1342         Buffer->ChangeTime.QuadPart = DirectoryCB->ObjectInformation->ChangeTime.QuadPart;
1343
1344         Buffer->AllocationSize.QuadPart = DirectoryCB->ObjectInformation->AllocationSize.QuadPart;
1345         Buffer->EndOfFile.QuadPart = DirectoryCB->ObjectInformation->EndOfFile.QuadPart;
1346
1347         Buffer->FileAttributes = ulFileAttribs;
1348
1349         if( DirectoryCB->NameInformation.FileName.Buffer[ 0] == L'.' &&
1350             BooleanFlagOn( pDeviceExt->DeviceFlags, AFS_DEVICE_FLAG_HIDE_DOT_NAMES))
1351         {
1352
1353             if ( Buffer->FileAttributes != FILE_ATTRIBUTE_NORMAL)
1354             {
1355
1356                 Buffer->FileAttributes |= FILE_ATTRIBUTE_HIDDEN;
1357             }
1358             else
1359             {
1360
1361                 Buffer->FileAttributes = FILE_ATTRIBUTE_HIDDEN;
1362             }
1363         }
1364
1365         *Length -= sizeof( FILE_NETWORK_OPEN_INFORMATION);
1366     }
1367     else
1368     {
1369
1370         ntStatus = STATUS_BUFFER_TOO_SMALL;
1371     }
1372
1373     return ntStatus;
1374 }
1375
1376 NTSTATUS
1377 AFSQueryStreamInfo( IN PIRP Irp,
1378                     IN AFSDirectoryCB *DirectoryCB,
1379                     IN OUT FILE_STREAM_INFORMATION *Buffer,
1380                     IN OUT PLONG Length)
1381 {
1382
1383     NTSTATUS ntStatus = STATUS_BUFFER_TOO_SMALL;
1384     ULONG ulCopyLength = 0;
1385     AFSDeviceExt *pDeviceExt = (AFSDeviceExt *)AFSRDRDeviceObject->DeviceExtension;
1386
1387     if( *Length >= FIELD_OFFSET( FILE_STREAM_INFORMATION, StreamName))
1388     {
1389
1390         RtlZeroMemory( Buffer,
1391                        *Length);
1392
1393         Buffer->NextEntryOffset = 0;
1394
1395
1396         if( !BooleanFlagOn( DirectoryCB->ObjectInformation->FileAttributes, FILE_ATTRIBUTE_DIRECTORY))
1397         {
1398
1399             if( *Length >= (LONG)(FIELD_OFFSET( FILE_STREAM_INFORMATION, StreamName) + 14))  // ::$DATA
1400             {
1401
1402                 ulCopyLength = 14;
1403
1404                 ntStatus = STATUS_SUCCESS;
1405             }
1406             else
1407             {
1408
1409                 ulCopyLength = *Length - FIELD_OFFSET( FILE_STREAM_INFORMATION, StreamName);
1410
1411                 ntStatus = STATUS_BUFFER_OVERFLOW;
1412             }
1413
1414             Buffer->StreamNameLength = 14; // ::$DATA
1415
1416             Buffer->StreamSize.QuadPart = DirectoryCB->ObjectInformation->EndOfFile.QuadPart;
1417
1418             Buffer->StreamAllocationSize.QuadPart = DirectoryCB->ObjectInformation->AllocationSize.QuadPart;
1419
1420             *Length -= FIELD_OFFSET( FILE_STREAM_INFORMATION, StreamName);
1421
1422             if( ulCopyLength > 0)
1423             {
1424
1425                 RtlCopyMemory( Buffer->StreamName,
1426                                L"::$DATA",
1427                                ulCopyLength);
1428
1429                 *Length -= ulCopyLength;
1430             }
1431         }
1432         else
1433         {
1434
1435             Buffer->StreamNameLength = 0;       // No stream for a directory
1436
1437             // The response size is zero
1438
1439             ntStatus = STATUS_SUCCESS;
1440         }
1441     }
1442
1443     return ntStatus;
1444 }
1445
1446 NTSTATUS
1447 AFSQueryAttribTagInfo( IN PIRP Irp,
1448                        IN AFSDirectoryCB *DirectoryCB,
1449                        IN OUT FILE_ATTRIBUTE_TAG_INFORMATION *Buffer,
1450                        IN OUT PLONG Length)
1451 {
1452
1453     NTSTATUS ntStatus = STATUS_BUFFER_TOO_SMALL;
1454     ULONG ulCopyLength = 0;
1455     AFSDeviceExt *pDeviceExt = (AFSDeviceExt *)AFSRDRDeviceObject->DeviceExtension;
1456     AFSCcb *pCcb = NULL;
1457     PIO_STACK_LOCATION pIrpSp = IoGetCurrentIrpStackLocation( Irp);
1458     AFSFileInfoCB stFileInfo;
1459     AFSDirectoryCB *pParentDirectoryCB = NULL;
1460     UNICODE_STRING uniParentPath;
1461     ULONG ulFileAttribs = 0;
1462
1463     if( *Length >= sizeof( FILE_ATTRIBUTE_TAG_INFORMATION))
1464     {
1465
1466         RtlZeroMemory( Buffer,
1467                        *Length);
1468
1469         ulFileAttribs = DirectoryCB->ObjectInformation->FileAttributes;
1470
1471         if( DirectoryCB->ObjectInformation->FileType == AFS_FILE_TYPE_SYMLINK)
1472         {
1473
1474             pCcb = (AFSCcb *)pIrpSp->FileObject->FsContext2;
1475
1476             pParentDirectoryCB = AFSGetParentEntry( pCcb->NameArray);
1477
1478             AFSRetrieveParentPath( &pCcb->FullFileName,
1479                                    &uniParentPath);
1480
1481             RtlZeroMemory( &stFileInfo,
1482                            sizeof( AFSFileInfoCB));
1483
1484             if( NT_SUCCESS( AFSRetrieveFileAttributes( pParentDirectoryCB,
1485                                                        DirectoryCB,
1486                                                        &uniParentPath,
1487                                                        NULL,
1488                                                        &stFileInfo)))
1489             {
1490                 ulFileAttribs = stFileInfo.FileAttributes;
1491
1492                 ulFileAttribs |= FILE_ATTRIBUTE_REPARSE_POINT;
1493             }
1494         }
1495
1496         Buffer->FileAttributes = ulFileAttribs;
1497
1498         if( DirectoryCB->NameInformation.FileName.Buffer[ 0] == L'.' &&
1499             BooleanFlagOn( pDeviceExt->DeviceFlags, AFS_DEVICE_FLAG_HIDE_DOT_NAMES))
1500         {
1501
1502             if ( Buffer->FileAttributes != FILE_ATTRIBUTE_NORMAL)
1503             {
1504
1505                 Buffer->FileAttributes |= FILE_ATTRIBUTE_HIDDEN;
1506             }
1507             else
1508             {
1509
1510                 Buffer->FileAttributes = FILE_ATTRIBUTE_HIDDEN;
1511             }
1512         }
1513
1514         if( BooleanFlagOn( DirectoryCB->ObjectInformation->FileAttributes, FILE_ATTRIBUTE_REPARSE_POINT))
1515         {
1516             Buffer->ReparseTag = IO_REPARSE_TAG_OPENAFS_DFS;
1517         }
1518
1519         *Length -= sizeof( FILE_ATTRIBUTE_TAG_INFORMATION);
1520
1521         ntStatus = STATUS_SUCCESS;
1522     }
1523
1524     return ntStatus;
1525 }
1526
1527 NTSTATUS
1528 AFSQueryRemoteProtocolInfo( IN PIRP Irp,
1529                             IN AFSDirectoryCB *DirectoryCB,
1530                             IN OUT FILE_REMOTE_PROTOCOL_INFORMATION *Buffer,
1531                             IN OUT PLONG Length)
1532 {
1533
1534     NTSTATUS ntStatus = STATUS_BUFFER_TOO_SMALL;
1535     ULONG ulCopyLength = 0;
1536     AFSDeviceExt *pDeviceExt = (AFSDeviceExt *)AFSRDRDeviceObject->DeviceExtension;
1537
1538     if( *Length >= sizeof( FILE_REMOTE_PROTOCOL_INFORMATION))
1539     {
1540
1541         RtlZeroMemory( Buffer,
1542                        *Length);
1543
1544         Buffer->StructureVersion = 1;
1545
1546         Buffer->StructureSize = sizeof(FILE_REMOTE_PROTOCOL_INFORMATION);
1547
1548         Buffer->Protocol = WNNC_NET_OPENAFS;
1549
1550         Buffer->ProtocolMajorVersion = 3;
1551
1552         Buffer->ProtocolMinorVersion = 0;
1553
1554         Buffer->ProtocolRevision = 0;
1555
1556         *Length -= sizeof( FILE_REMOTE_PROTOCOL_INFORMATION);
1557
1558         ntStatus = STATUS_SUCCESS;
1559     }
1560
1561     return ntStatus;
1562 }
1563
1564 NTSTATUS
1565 AFSSetBasicInfo( IN PIRP Irp,
1566                  IN AFSDirectoryCB *DirectoryCB)
1567 {
1568     NTSTATUS ntStatus = STATUS_SUCCESS;
1569     PFILE_BASIC_INFORMATION pBuffer;
1570     PIO_STACK_LOCATION pIrpSp = IoGetCurrentIrpStackLocation( Irp);
1571     ULONG ulNotifyFilter = 0;
1572     AFSCcb *pCcb = NULL;
1573
1574     __Enter
1575     {
1576
1577         pCcb = (AFSCcb *)pIrpSp->FileObject->FsContext2;
1578
1579         pBuffer = (PFILE_BASIC_INFORMATION)Irp->AssociatedIrp.SystemBuffer;
1580
1581         pCcb->FileUnwindInfo.FileAttributes = (ULONG)-1;
1582
1583         if( pBuffer->FileAttributes != (ULONGLONG)0)
1584         {
1585
1586             if( DirectoryCB->ObjectInformation->Fcb->Header.NodeTypeCode == AFS_FILE_FCB &&
1587                 BooleanFlagOn( pBuffer->FileAttributes, FILE_ATTRIBUTE_DIRECTORY))
1588             {
1589
1590                 try_return( ntStatus = STATUS_INVALID_PARAMETER);
1591             }
1592
1593             if( DirectoryCB->ObjectInformation->Fcb->Header.NodeTypeCode == AFS_DIRECTORY_FCB)
1594             {
1595
1596                 pBuffer->FileAttributes |= FILE_ATTRIBUTE_DIRECTORY;
1597             }
1598
1599             pCcb->FileUnwindInfo.FileAttributes = DirectoryCB->ObjectInformation->FileAttributes;
1600
1601             DirectoryCB->ObjectInformation->FileAttributes = pBuffer->FileAttributes;
1602
1603             ulNotifyFilter |= FILE_NOTIFY_CHANGE_ATTRIBUTES;
1604
1605             SetFlag( DirectoryCB->ObjectInformation->Fcb->Flags, AFS_FCB_FLAG_FILE_MODIFIED);
1606         }
1607
1608         pCcb->FileUnwindInfo.CreationTime.QuadPart = (ULONGLONG)-1;
1609
1610         if( pBuffer->CreationTime.QuadPart != (ULONGLONG)-1 &&
1611             pBuffer->CreationTime.QuadPart != (ULONGLONG)0)
1612         {
1613
1614             pCcb->FileUnwindInfo.CreationTime.QuadPart = DirectoryCB->ObjectInformation->CreationTime.QuadPart;
1615
1616             DirectoryCB->ObjectInformation->CreationTime.QuadPart = pBuffer->CreationTime.QuadPart;
1617
1618             ulNotifyFilter |= FILE_NOTIFY_CHANGE_CREATION;
1619
1620             SetFlag( DirectoryCB->ObjectInformation->Fcb->Flags, AFS_FCB_FLAG_FILE_MODIFIED | AFS_FCB_FLAG_UPDATE_CREATE_TIME);
1621         }
1622
1623         pCcb->FileUnwindInfo.LastAccessTime.QuadPart = (ULONGLONG)-1;
1624
1625         if( pBuffer->LastAccessTime.QuadPart != (ULONGLONG)-1 &&
1626             pBuffer->LastAccessTime.QuadPart != (ULONGLONG)0)
1627         {
1628
1629             pCcb->FileUnwindInfo.LastAccessTime.QuadPart = DirectoryCB->ObjectInformation->LastAccessTime.QuadPart;
1630
1631             DirectoryCB->ObjectInformation->LastAccessTime.QuadPart = pBuffer->LastAccessTime.QuadPart;
1632
1633             ulNotifyFilter |= FILE_NOTIFY_CHANGE_LAST_ACCESS;
1634
1635             SetFlag( DirectoryCB->ObjectInformation->Fcb->Flags, AFS_FCB_FLAG_FILE_MODIFIED | AFS_FCB_FLAG_UPDATE_ACCESS_TIME);
1636         }
1637
1638         pCcb->FileUnwindInfo.LastWriteTime.QuadPart = (ULONGLONG)-1;
1639
1640         if( pBuffer->LastWriteTime.QuadPart != (ULONGLONG)-1 &&
1641             pBuffer->LastWriteTime.QuadPart != (ULONGLONG)0)
1642         {
1643
1644             pCcb->FileUnwindInfo.LastWriteTime.QuadPart = DirectoryCB->ObjectInformation->LastWriteTime.QuadPart;
1645
1646             DirectoryCB->ObjectInformation->LastWriteTime.QuadPart = pBuffer->LastWriteTime.QuadPart;
1647
1648             ulNotifyFilter |= FILE_NOTIFY_CHANGE_LAST_WRITE;
1649
1650             SetFlag( DirectoryCB->ObjectInformation->Fcb->Flags, AFS_FCB_FLAG_FILE_MODIFIED | AFS_FCB_FLAG_UPDATE_LAST_WRITE_TIME);
1651         }
1652
1653         pCcb->FileUnwindInfo.ChangeTime.QuadPart = (ULONGLONG)-1;
1654
1655         if( pBuffer->ChangeTime.QuadPart != (ULONGLONG)-1 &&
1656             pBuffer->ChangeTime.QuadPart != (ULONGLONG)0)
1657         {
1658
1659             pCcb->FileUnwindInfo.ChangeTime.QuadPart = DirectoryCB->ObjectInformation->ChangeTime.QuadPart;
1660
1661             DirectoryCB->ObjectInformation->ChangeTime.QuadPart = pBuffer->ChangeTime.QuadPart;
1662
1663             ulNotifyFilter |= FILE_NOTIFY_CHANGE_LAST_ACCESS;
1664
1665             SetFlag( DirectoryCB->ObjectInformation->Fcb->Flags, AFS_FCB_FLAG_FILE_MODIFIED | AFS_FCB_FLAG_UPDATE_CHANGE_TIME);
1666         }
1667
1668         if( ulNotifyFilter > 0)
1669         {
1670
1671             if( DirectoryCB->ObjectInformation->ParentObjectInformation != NULL)
1672             {
1673
1674                 AFSFsRtlNotifyFullReportChange( DirectoryCB->ObjectInformation->ParentObjectInformation,
1675                                                 pCcb,
1676                                                 (ULONG)ulNotifyFilter,
1677                                                 (ULONG)FILE_ACTION_MODIFIED);
1678             }
1679         }
1680
1681 try_exit:
1682
1683         NOTHING;
1684     }
1685
1686     return ntStatus;
1687 }
1688
1689 NTSTATUS
1690 AFSSetDispositionInfo( IN PIRP Irp,
1691                        IN AFSDirectoryCB *DirectoryCB)
1692 {
1693     NTSTATUS ntStatus = STATUS_SUCCESS;
1694     PFILE_DISPOSITION_INFORMATION pBuffer;
1695     PIO_STACK_LOCATION pIrpSp = IoGetCurrentIrpStackLocation( Irp);
1696     AFSFcb *pFcb = NULL;
1697     AFSCcb *pCcb = NULL;
1698
1699     __Enter
1700     {
1701
1702         pBuffer = (PFILE_DISPOSITION_INFORMATION)Irp->AssociatedIrp.SystemBuffer;
1703
1704         pFcb = (AFSFcb *)pIrpSp->FileObject->FsContext;
1705
1706         pCcb = (AFSCcb *)pIrpSp->FileObject->FsContext2;
1707
1708         //
1709         // Can't delete the root
1710         //
1711
1712         if( pFcb->Header.NodeTypeCode == AFS_ROOT_FCB)
1713         {
1714
1715             AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
1716                           AFS_TRACE_LEVEL_ERROR,
1717                           "AFSSetDispositionInfo Attempt to delete root entry\n");
1718
1719             try_return( ntStatus = STATUS_CANNOT_DELETE);
1720         }
1721
1722         //
1723         // If the file is read only then do not allow the delete
1724         //
1725
1726         if( BooleanFlagOn( DirectoryCB->ObjectInformation->FileAttributes, FILE_ATTRIBUTE_READONLY))
1727         {
1728
1729             AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
1730                           AFS_TRACE_LEVEL_ERROR,
1731                           "AFSSetDispositionInfo Attempt to delete read only entry %wZ\n",
1732                           &DirectoryCB->NameInformation.FileName);
1733
1734             try_return( ntStatus = STATUS_CANNOT_DELETE);
1735         }
1736
1737         if( pBuffer->DeleteFile)
1738         {
1739
1740             //
1741             // Check if the caller can delete the file
1742             //
1743
1744             ntStatus = AFSNotifyDelete( DirectoryCB,
1745                                         TRUE);
1746
1747             if( !NT_SUCCESS( ntStatus))
1748             {
1749
1750                 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
1751                               AFS_TRACE_LEVEL_ERROR,
1752                               "AFSSetDispositionInfo Cannot delete entry %wZ Status %08lX\n",
1753                               &DirectoryCB->NameInformation.FileName,
1754                               ntStatus);
1755
1756                 try_return( ntStatus);
1757             }
1758
1759             if( pFcb->Header.NodeTypeCode == AFS_DIRECTORY_FCB)
1760             {
1761
1762                 //
1763                 // Check if this is a directory that there are not currently other opens
1764                 //
1765
1766                 if( pFcb->ObjectInformation->Specific.Directory.ChildOpenHandleCount > 0)
1767                 {
1768
1769                     AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
1770                                   AFS_TRACE_LEVEL_ERROR,
1771                                   "AFSSetDispositionInfo Attempt to delete directory %wZ with open %u handles\n",
1772                                   &DirectoryCB->NameInformation.FileName,
1773                                   pFcb->ObjectInformation->Specific.Directory.ChildOpenHandleCount);
1774
1775                     try_return( ntStatus = STATUS_DIRECTORY_NOT_EMPTY);
1776                 }
1777
1778                 if( !AFSIsDirectoryEmptyForDelete( pFcb))
1779                 {
1780
1781                     AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
1782                                   AFS_TRACE_LEVEL_ERROR,
1783                                   "AFSSetDispositionInfo Attempt to delete non-empty directory %wZ\n",
1784                                   &DirectoryCB->NameInformation.FileName);
1785
1786                     try_return( ntStatus = STATUS_DIRECTORY_NOT_EMPTY);
1787                 }
1788             }
1789             else
1790             {
1791
1792                 //
1793                 // Attempt to flush any outstanding data
1794                 //
1795
1796                 if( !MmFlushImageSection( &pFcb->NPFcb->SectionObjectPointers,
1797                                           MmFlushForDelete))
1798                 {
1799
1800                     AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
1801                                   AFS_TRACE_LEVEL_ERROR,
1802                                   "AFSSetDispositionInfo Failed to flush image section for delete Entry %wZ\n",
1803                                   &DirectoryCB->NameInformation.FileName);
1804
1805                     try_return( ntStatus = STATUS_CANNOT_DELETE);
1806                 }
1807
1808                 //
1809                 // Purge the cache as well
1810                 //
1811
1812                 if( pFcb->NPFcb->SectionObjectPointers.DataSectionObject != NULL)
1813                 {
1814
1815                     CcPurgeCacheSection( &pFcb->NPFcb->SectionObjectPointers,
1816                                          NULL,
1817                                          0,
1818                                          TRUE);
1819                 }
1820             }
1821
1822             AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
1823                           AFS_TRACE_LEVEL_VERBOSE,
1824                           "AFSSetDispositionInfo Setting PENDING_DELETE on DirEntry  %p Name %wZ\n",
1825                           DirectoryCB,
1826                           &DirectoryCB->NameInformation.FileName);
1827
1828             SetFlag( pCcb->DirectoryCB->Flags, AFS_DIR_ENTRY_PENDING_DELETE);
1829         }
1830         else
1831         {
1832
1833             ClearFlag( pCcb->DirectoryCB->Flags, AFS_DIR_ENTRY_PENDING_DELETE);
1834         }
1835
1836         //
1837         // OK, should be good to go, set the flag in the file object
1838         //
1839
1840         pIrpSp->FileObject->DeletePending = pBuffer->DeleteFile;
1841
1842 try_exit:
1843
1844         NOTHING;
1845     }
1846
1847     return ntStatus;
1848 }
1849
1850 NTSTATUS
1851 AFSSetRenameInfo( IN PIRP Irp)
1852 {
1853
1854     NTSTATUS ntStatus = STATUS_SUCCESS;
1855     PIO_STACK_LOCATION pIrpSp = IoGetCurrentIrpStackLocation( Irp);
1856     IO_STATUS_BLOCK stIoSb = {0,0};
1857     AFSFcb *pSrcFcb = NULL, *pTargetDcb = NULL, *pTargetFcb = NULL;
1858     AFSCcb *pSrcCcb = NULL, *pTargetDirCcb = NULL;
1859     PFILE_OBJECT pSrcFileObj = pIrpSp->FileObject;
1860     PFILE_OBJECT pTargetFileObj = pIrpSp->Parameters.SetFile.FileObject;
1861     PFILE_RENAME_INFORMATION pRenameInfo = NULL;
1862     UNICODE_STRING uniTargetName, uniSourceName;
1863     BOOLEAN bReplaceIfExists = FALSE;
1864     UNICODE_STRING uniShortName;
1865     AFSDirectoryCB *pTargetDirEntry = NULL;
1866     ULONG ulTargetCRC = 0;
1867     BOOLEAN bTargetEntryExists = FALSE;
1868     AFSObjectInfoCB *pSrcObject = NULL, *pTargetObject = NULL;
1869     AFSObjectInfoCB *pSrcParentObject = NULL, *pTargetParentObject = NULL;
1870     AFSFileID stNewFid, stTmpTargetFid;
1871     ULONG ulNotificationAction = 0, ulNotifyFilter = 0;
1872     UNICODE_STRING uniFullTargetPath;
1873     BOOLEAN bCommonParent = FALSE;
1874     ULONG oldFileIndex;
1875     BOOLEAN bReleaseVolumeLock = FALSE;
1876     BOOLEAN bReleaseTargetDirLock = FALSE;
1877     BOOLEAN bReleaseSourceDirLock = FALSE;
1878
1879     __Enter
1880     {
1881
1882         bReplaceIfExists = pIrpSp->Parameters.SetFile.ReplaceIfExists;
1883
1884         pSrcFcb = (AFSFcb *)pSrcFileObj->FsContext;
1885         pSrcCcb = (AFSCcb *)pSrcFileObj->FsContext2;
1886
1887         pSrcObject = pSrcFcb->ObjectInformation;
1888
1889         //
1890         // Perform some basic checks to ensure FS integrity
1891         //
1892
1893         if( pSrcFcb->Header.NodeTypeCode == AFS_ROOT_FCB)
1894         {
1895
1896             //
1897             // Can't rename the root directory
1898             //
1899
1900             AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
1901                           AFS_TRACE_LEVEL_ERROR,
1902                           "AFSSetRenameInfo Attempt to rename root entry\n");
1903
1904             try_return( ntStatus = STATUS_INVALID_PARAMETER);
1905         }
1906
1907         if( pSrcFcb->Header.NodeTypeCode == AFS_DIRECTORY_FCB)
1908         {
1909
1910             //
1911             // If there are any open children then fail the rename
1912             //
1913
1914             if( pSrcFcb->ObjectInformation->Specific.Directory.ChildOpenHandleCount > 0)
1915             {
1916
1917                 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
1918                               AFS_TRACE_LEVEL_ERROR,
1919                               "AFSSetRenameInfo Attempt to rename directory with open children %wZ\n",
1920                               &pSrcCcb->DirectoryCB->NameInformation.FileName);
1921
1922                 try_return( ntStatus = STATUS_ACCESS_DENIED);
1923             }
1924         }
1925         else
1926         {
1927
1928             if( pSrcFcb->OpenHandleCount > 1)
1929             {
1930
1931                 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
1932                               AFS_TRACE_LEVEL_ERROR,
1933                               "AFSSetRenameInfo Attempt to rename directory with open references %wZ\n",
1934                               &pSrcCcb->DirectoryCB->NameInformation.FileName);
1935
1936                 try_return( ntStatus = STATUS_ACCESS_DENIED);
1937             }
1938         }
1939
1940         //
1941         // Resolve the target fileobject
1942         //
1943
1944         if( pTargetFileObj == NULL)
1945         {
1946
1947             //
1948             // This is a simple rename. Here the target directory is the same as the source parent directory
1949             // and the name is retrieved from the system buffer information
1950             //
1951
1952             pRenameInfo = (PFILE_RENAME_INFORMATION)Irp->AssociatedIrp.SystemBuffer;
1953
1954             pTargetParentObject = pSrcFcb->ObjectInformation->ParentObjectInformation;
1955
1956             pTargetDcb = pTargetParentObject->Fcb;
1957
1958             uniTargetName.Length = (USHORT)pRenameInfo->FileNameLength;
1959             uniTargetName.Buffer = (PWSTR)&pRenameInfo->FileName;
1960         }
1961         else
1962         {
1963
1964             //
1965             // So here we have the target directory taken from the targetfile object
1966             //
1967
1968             pTargetDcb = (AFSFcb *)pTargetFileObj->FsContext;
1969
1970             pTargetDirCcb = (AFSCcb *)pTargetFileObj->FsContext2;
1971
1972             pTargetParentObject = (AFSObjectInfoCB *)pTargetDcb->ObjectInformation;
1973
1974             //
1975             // Grab the target name which we setup in the IRP_MJ_CREATE handler. By how we set this up
1976             // it is only the target component of the rename operation
1977             //
1978
1979             uniTargetName = *((PUNICODE_STRING)&pTargetFileObj->FileName);
1980         }
1981
1982         //
1983         // We do not allow cross-volume renames to occur
1984         //
1985
1986         if( pTargetParentObject->VolumeCB != pSrcObject->VolumeCB)
1987         {
1988
1989             AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
1990                           AFS_TRACE_LEVEL_ERROR,
1991                           "AFSSetRenameInfo Attempt to rename directory to different volume %wZ\n",
1992                           &pSrcCcb->DirectoryCB->NameInformation.FileName);
1993
1994             try_return( ntStatus = STATUS_NOT_SAME_DEVICE);
1995         }
1996
1997         //
1998         // If the target exists be sure the ReplaceIfExists flag is set
1999         //
2000
2001         AFSAcquireExcl( pTargetParentObject->VolumeCB->VolumeLock,
2002                         TRUE);
2003
2004         bReleaseVolumeLock = TRUE;
2005
2006         ulTargetCRC = AFSGenerateCRC( &uniTargetName,
2007                                       FALSE);
2008
2009         AFSAcquireExcl( pTargetParentObject->Specific.Directory.DirectoryNodeHdr.TreeLock,
2010                         TRUE);
2011
2012         bReleaseTargetDirLock = TRUE;
2013
2014         if( pTargetParentObject != pSrcFcb->ObjectInformation->ParentObjectInformation)
2015         {
2016             AFSAcquireExcl( pSrcFcb->ObjectInformation->ParentObjectInformation->Specific.Directory.DirectoryNodeHdr.TreeLock,
2017                             TRUE);
2018
2019             bReleaseSourceDirLock = TRUE;
2020         }
2021
2022         AFSLocateCaseSensitiveDirEntry( pTargetParentObject->Specific.Directory.DirectoryNodeHdr.CaseSensitiveTreeHead,
2023                                         ulTargetCRC,
2024                                         &pTargetDirEntry);
2025
2026         if( pTargetDirEntry == NULL)
2027         {
2028
2029             //
2030             // Missed so perform a case insensitive lookup
2031             //
2032
2033             ulTargetCRC = AFSGenerateCRC( &uniTargetName,
2034                                           TRUE);
2035
2036             AFSLocateCaseInsensitiveDirEntry( pTargetParentObject->Specific.Directory.DirectoryNodeHdr.CaseInsensitiveTreeHead,
2037                                               ulTargetCRC,
2038                                               &pTargetDirEntry);
2039         }
2040
2041         if( pTargetDirEntry == NULL && RtlIsNameLegalDOS8Dot3( &uniTargetName,
2042                                                                NULL,
2043                                                                NULL))
2044         {
2045             //
2046             // Try the short name
2047             //
2048             AFSLocateShortNameDirEntry( pTargetParentObject->Specific.Directory.ShortNameTree,
2049                                         ulTargetCRC,
2050                                         &pTargetDirEntry);
2051         }
2052
2053         //
2054         // Increment our ref count on the dir entry
2055         //
2056
2057         if( pTargetDirEntry != NULL)
2058         {
2059
2060             ASSERT( pTargetParentObject == pTargetDirEntry->ObjectInformation->ParentObjectInformation);
2061
2062             InterlockedIncrement( &pTargetDirEntry->OpenReferenceCount);
2063
2064             if( !bReplaceIfExists)
2065             {
2066
2067                 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
2068                               AFS_TRACE_LEVEL_ERROR,
2069                               "AFSSetRenameInfo Attempt to rename directory with target collision %wZ Target %wZ\n",
2070                               &pSrcCcb->DirectoryCB->NameInformation.FileName,
2071                               &pTargetDirEntry->NameInformation.FileName);
2072
2073                 try_return( ntStatus = STATUS_OBJECT_NAME_COLLISION);
2074             }
2075
2076             AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
2077                           AFS_TRACE_LEVEL_ERROR,
2078                           "AFSSetRenameInfo Target %wZ exists DE %p Count %08lX, performing delete of target\n",
2079                           &pTargetDirEntry->NameInformation.FileName,
2080                           pTargetDirEntry,
2081                           pTargetDirEntry->OpenReferenceCount);
2082
2083             //
2084             // Pull the directory entry from the parent
2085             //
2086
2087             AFSRemoveDirNodeFromParent( pTargetParentObject,
2088                                         pTargetDirEntry,
2089                                         FALSE);
2090
2091             bTargetEntryExists = TRUE;
2092         }
2093         else
2094         {
2095             AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
2096                           AFS_TRACE_LEVEL_ERROR,
2097                           "AFSSetRenameInfo Target Target does NOT exist, normal rename\n");
2098         }
2099
2100         //
2101         // Extract off the final component name from the Fcb
2102         //
2103
2104         uniSourceName.Length = (USHORT)pSrcCcb->DirectoryCB->NameInformation.FileName.Length;
2105         uniSourceName.MaximumLength = uniSourceName.Length;
2106
2107         uniSourceName.Buffer = pSrcCcb->DirectoryCB->NameInformation.FileName.Buffer;
2108
2109         //
2110         // The quick check to see if they are not really performing a rename
2111         // Do the names match? Only do this where the parent directories are
2112         // the same
2113         //
2114
2115         if( pTargetParentObject == pSrcFcb->ObjectInformation->ParentObjectInformation)
2116         {
2117
2118             bCommonParent = TRUE;
2119
2120             if( FsRtlAreNamesEqual( &uniTargetName,
2121                                     &uniSourceName,
2122                                     FALSE,
2123                                     NULL))
2124             {
2125                 try_return( ntStatus = STATUS_SUCCESS);
2126             }
2127         }
2128         else
2129         {
2130
2131             bCommonParent = FALSE;
2132         }
2133
2134         //
2135         // We need to remove the DirEntry from the parent node, update the index
2136         // and reinsert it into the parent tree. Note that for entries with the
2137         // same parent we do not pull the node from the enumeration list
2138         //
2139
2140         AFSRemoveDirNodeFromParent( pSrcFcb->ObjectInformation->ParentObjectInformation,
2141                                     pSrcCcb->DirectoryCB,
2142                                     !bCommonParent);
2143
2144         oldFileIndex = pSrcCcb->DirectoryCB->FileIndex;
2145
2146         if( !bCommonParent)
2147         {
2148
2149             //
2150             // We always need to update the FileIndex since this entry will be put at the 'end'
2151             // of the enumeraiton list. If we don't it will cause recursion ... We do this
2152             // here to cover any failures which might occur below
2153             //
2154
2155             pSrcCcb->DirectoryCB->FileIndex =
2156                             (ULONG)InterlockedIncrement( &pTargetDcb->ObjectInformation->ParentObjectInformation->Specific.Directory.DirectoryNodeHdr.ContentIndex);
2157         }
2158
2159         //
2160         // OK, this is a simple rename. Issue the rename
2161         // request to the service.
2162         //
2163
2164         ntStatus = AFSNotifyRename( pSrcFcb->ObjectInformation,
2165                                     pSrcFcb->ObjectInformation->ParentObjectInformation,
2166                                     pTargetDcb->ObjectInformation,
2167                                     pSrcCcb->DirectoryCB,
2168                                     &uniTargetName,
2169                                     &stNewFid);
2170
2171         if( !NT_SUCCESS( ntStatus))
2172         {
2173
2174             //
2175             // Attempt to re-insert the directory entry
2176             //
2177
2178             pSrcCcb->DirectoryCB->FileIndex = oldFileIndex;
2179             AFSInsertDirectoryNode( pSrcFcb->ObjectInformation->ParentObjectInformation,
2180                                     pSrcCcb->DirectoryCB,
2181                                     !bCommonParent);
2182
2183             AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
2184                           AFS_TRACE_LEVEL_ERROR,
2185                           "AFSSetRenameInfo Failed rename of %wZ to target %wZ Status %08lX\n",
2186                           &pSrcCcb->DirectoryCB->NameInformation.FileName,
2187                           &uniTargetName,
2188                           ntStatus);
2189
2190             try_return( ntStatus);
2191         }
2192
2193         //
2194         // Set the notification up for the source file
2195         //
2196
2197         if( pSrcCcb->DirectoryCB->ObjectInformation->ParentObjectInformation == pTargetParentObject &&
2198             !bTargetEntryExists)
2199         {
2200
2201             ulNotificationAction = FILE_ACTION_RENAMED_OLD_NAME;
2202         }
2203         else
2204         {
2205
2206             ulNotificationAction = FILE_ACTION_REMOVED;
2207         }
2208
2209         if( pSrcCcb->DirectoryCB->ObjectInformation->FileType == AFS_FILE_TYPE_DIRECTORY)
2210         {
2211
2212             ulNotifyFilter = FILE_NOTIFY_CHANGE_DIR_NAME;
2213         }
2214         else
2215         {
2216
2217             ulNotifyFilter = FILE_NOTIFY_CHANGE_FILE_NAME;
2218         }
2219
2220         AFSFsRtlNotifyFullReportChange( pSrcCcb->DirectoryCB->ObjectInformation->ParentObjectInformation,
2221                                         pSrcCcb,
2222                                         (ULONG)ulNotifyFilter,
2223                                         (ULONG)ulNotificationAction);
2224
2225         //
2226         // Update the name in the dir entry.
2227         //
2228
2229         ntStatus = AFSUpdateDirEntryName( pSrcCcb->DirectoryCB,
2230                                           &uniTargetName);
2231
2232         if( !NT_SUCCESS( ntStatus))
2233         {
2234
2235             //
2236             // Attempt to re-insert the directory entry
2237             //
2238
2239             pSrcCcb->DirectoryCB->FileIndex = oldFileIndex;
2240             AFSInsertDirectoryNode( pSrcFcb->ObjectInformation->ParentObjectInformation,
2241                                     pSrcCcb->DirectoryCB,
2242                                     !bCommonParent);
2243
2244             AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
2245                           AFS_TRACE_LEVEL_ERROR,
2246                           "AFSSetRenameInfo Failed update of dir entry %wZ to target %wZ Status %08lX\n",
2247                           &pSrcCcb->DirectoryCB->NameInformation.FileName,
2248                           &uniTargetName,
2249                           ntStatus);
2250
2251             try_return( ntStatus);
2252         }
2253
2254         //
2255         // Update the object information block, if needed
2256         //
2257
2258         if( !AFSIsEqualFID( &pSrcObject->FileId,
2259                             &stNewFid))
2260         {
2261
2262             //
2263             // Remove the old information entry
2264             //
2265
2266             AFSRemoveHashEntry( &pSrcObject->VolumeCB->ObjectInfoTree.TreeHead,
2267                                 &pSrcObject->TreeEntry);
2268
2269             RtlCopyMemory( &pSrcObject->FileId,
2270                            &stNewFid,
2271                            sizeof( AFSFileID));
2272
2273             //
2274             // Insert the entry into the new object table.
2275             //
2276
2277             pSrcObject->TreeEntry.HashIndex = AFSCreateLowIndex( &pSrcObject->FileId);
2278
2279             if( pSrcObject->VolumeCB->ObjectInfoTree.TreeHead == NULL)
2280             {
2281
2282                 pSrcObject->VolumeCB->ObjectInfoTree.TreeHead = &pSrcObject->TreeEntry;
2283             }
2284             else
2285             {
2286
2287                 AFSInsertHashEntry( pSrcObject->VolumeCB->ObjectInfoTree.TreeHead,
2288                                     &pSrcObject->TreeEntry);
2289             }
2290         }
2291
2292         //
2293         // Update the hash values for the name trees.
2294         //
2295
2296         pSrcCcb->DirectoryCB->CaseSensitiveTreeEntry.HashIndex = AFSGenerateCRC( &pSrcCcb->DirectoryCB->NameInformation.FileName,
2297                                                                                  FALSE);
2298
2299         pSrcCcb->DirectoryCB->CaseInsensitiveTreeEntry.HashIndex = AFSGenerateCRC( &pSrcCcb->DirectoryCB->NameInformation.FileName,
2300                                                                                    TRUE);
2301
2302         if( pSrcCcb->DirectoryCB->NameInformation.ShortNameLength > 0 &&
2303             !RtlIsNameLegalDOS8Dot3( &pSrcCcb->DirectoryCB->NameInformation.FileName,
2304                                      NULL,
2305                                      NULL))
2306         {
2307
2308             uniShortName.Length = pSrcCcb->DirectoryCB->NameInformation.ShortNameLength;
2309             uniShortName.MaximumLength = uniShortName.Length;
2310             uniShortName.Buffer = pSrcCcb->DirectoryCB->NameInformation.ShortName;
2311
2312             pSrcCcb->DirectoryCB->Type.Data.ShortNameTreeEntry.HashIndex = AFSGenerateCRC( &uniShortName,
2313                                                                                            TRUE);
2314
2315             AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
2316                           AFS_TRACE_LEVEL_VERBOSE,
2317                           "AFSSetRenameInfo Initialized short name hash for %wZ longname %wZ\n",
2318                           &uniShortName,
2319                           &pSrcCcb->DirectoryCB->NameInformation.FileName);
2320         }
2321         else
2322         {
2323
2324             pSrcCcb->DirectoryCB->Type.Data.ShortNameTreeEntry.HashIndex = 0;
2325         }
2326
2327         if( !bCommonParent)
2328         {
2329
2330             //
2331             // Update the file index for the object in the new parent
2332             //
2333
2334             pSrcCcb->DirectoryCB->FileIndex = (ULONG)InterlockedIncrement( &pTargetParentObject->Specific.Directory.DirectoryNodeHdr.ContentIndex);
2335         }
2336
2337         //
2338         // Re-insert the directory entry
2339         //
2340
2341         AFSInsertDirectoryNode( pTargetParentObject,
2342                                 pSrcCcb->DirectoryCB,
2343                                 !bCommonParent);
2344
2345         //
2346         // Update the parent pointer in the source object if they are different
2347         //
2348
2349         if( pSrcCcb->DirectoryCB->ObjectInformation->ParentObjectInformation != pTargetParentObject)
2350         {
2351
2352             InterlockedDecrement( &pSrcCcb->DirectoryCB->ObjectInformation->ParentObjectInformation->Specific.Directory.ChildOpenHandleCount);
2353
2354             InterlockedDecrement( &pSrcCcb->DirectoryCB->ObjectInformation->ParentObjectInformation->Specific.Directory.ChildOpenReferenceCount);
2355
2356             InterlockedIncrement( &pTargetParentObject->Specific.Directory.ChildOpenHandleCount);
2357
2358             InterlockedIncrement( &pTargetParentObject->Specific.Directory.ChildOpenReferenceCount);
2359
2360             pSrcCcb->DirectoryCB->ObjectInformation->ParentObjectInformation = pTargetParentObject;
2361
2362             ulNotificationAction = FILE_ACTION_ADDED;
2363         }
2364         else
2365         {
2366
2367             ulNotificationAction = FILE_ACTION_RENAMED_NEW_NAME;
2368         }
2369
2370         //
2371         // Now update the notification for the target file
2372         //
2373
2374         AFSFsRtlNotifyFullReportChange( pTargetParentObject->ParentObjectInformation,
2375                                         pSrcCcb,
2376                                         (ULONG)ulNotifyFilter,
2377                                         (ULONG)ulNotificationAction);
2378
2379         //
2380         // If we performed the rename of the target because it existed, we now need to
2381         // delete the tmp target we created above
2382         //
2383
2384         if( bTargetEntryExists)
2385         {
2386
2387             AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
2388                           AFS_TRACE_LEVEL_VERBOSE,
2389                           "AFSSetRenameInfo Setting DELETE flag in dir entry %p name %wZ\n",
2390                           pTargetDirEntry,
2391                           &pTargetDirEntry->NameInformation.FileName);
2392
2393             SetFlag( pTargetDirEntry->Flags, AFS_DIR_ENTRY_DELETED);
2394
2395             //
2396             // Try and purge the cache map if this is a file
2397             //
2398
2399             if( pTargetDirEntry->ObjectInformation->FileType == AFS_FILE_TYPE_FILE &&
2400                 pTargetDirEntry->ObjectInformation->Fcb != NULL &&
2401                 pTargetDirEntry->OpenReferenceCount > 1)
2402             {
2403
2404                 pTargetFcb = pTargetDirEntry->ObjectInformation->Fcb;
2405
2406                 AFSAcquireExcl( &pTargetFcb->NPFcb->Resource,
2407                                 TRUE);
2408
2409                 //
2410                 // Close the section in the event it was mapped
2411                 //
2412
2413                 if( !MmForceSectionClosed( &pTargetFcb->NPFcb->SectionObjectPointers,
2414                                            TRUE))
2415                 {
2416
2417                     AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
2418                                   AFS_TRACE_LEVEL_ERROR,
2419                                   "AFSSetRenameInfo Failed to delete section for target file %wZ\n",
2420                                   &pTargetDirEntry->NameInformation.FileName);
2421                 }
2422
2423                 AFSReleaseResource( &pTargetFcb->NPFcb->Resource);
2424             }
2425
2426             ASSERT( pTargetDirEntry->OpenReferenceCount > 0);
2427
2428             InterlockedDecrement( &pTargetDirEntry->OpenReferenceCount); // The count we added above
2429
2430             if( pTargetDirEntry->OpenReferenceCount == 0)
2431             {
2432
2433                 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
2434                               AFS_TRACE_LEVEL_VERBOSE,
2435                               "AFSSetRenameInfo Deleting dir entry %p name %wZ\n",
2436                               pTargetDirEntry,
2437                               &pTargetDirEntry->NameInformation.FileName);
2438
2439                 AFSDeleteDirEntry( pTargetParentObject,
2440                                    pTargetDirEntry);
2441             }
2442
2443             pTargetDirEntry = NULL;
2444         }
2445
2446 try_exit:
2447
2448
2449         if( !NT_SUCCESS( ntStatus))
2450         {
2451
2452             if( bTargetEntryExists)
2453             {
2454                 AFSInsertDirectoryNode( pTargetDirEntry->ObjectInformation->ParentObjectInformation,
2455                                         pTargetDirEntry,
2456                                         FALSE);
2457             }
2458         }
2459
2460         if( pTargetDirEntry != NULL)
2461         {
2462
2463             InterlockedDecrement( &pTargetDirEntry->OpenReferenceCount);
2464         }
2465
2466         if( bReleaseVolumeLock)
2467         {
2468             AFSReleaseResource( pTargetParentObject->VolumeCB->VolumeLock);
2469         }
2470
2471         if( bReleaseTargetDirLock)
2472         {
2473             AFSReleaseResource( pTargetParentObject->Specific.Directory.DirectoryNodeHdr.TreeLock);
2474         }
2475
2476         if( bReleaseSourceDirLock)
2477         {
2478             AFSReleaseResource( pSrcFcb->ObjectInformation->ParentObjectInformation->Specific.Directory.DirectoryNodeHdr.TreeLock);
2479         }
2480     }
2481
2482     return ntStatus;
2483 }
2484
2485 NTSTATUS
2486 AFSSetPositionInfo( IN PIRP Irp,
2487                     IN AFSDirectoryCB *DirectoryCB)
2488 {
2489     NTSTATUS ntStatus = STATUS_SUCCESS;
2490     PFILE_POSITION_INFORMATION pBuffer;
2491     PIO_STACK_LOCATION pIrpSp = IoGetCurrentIrpStackLocation( Irp);
2492
2493     pBuffer = (PFILE_POSITION_INFORMATION)Irp->AssociatedIrp.SystemBuffer;
2494
2495     pIrpSp->FileObject->CurrentByteOffset.QuadPart = pBuffer->CurrentByteOffset.QuadPart;
2496
2497     return ntStatus;
2498 }
2499
2500 NTSTATUS
2501 AFSSetAllocationInfo( IN PIRP Irp,
2502                       IN AFSDirectoryCB *DirectoryCB)
2503 {
2504     NTSTATUS ntStatus = STATUS_SUCCESS;
2505     PFILE_ALLOCATION_INFORMATION pBuffer;
2506     BOOLEAN bReleasePaging = FALSE;
2507     BOOLEAN bTellCc = FALSE;
2508     BOOLEAN bTellService = FALSE;
2509     PIO_STACK_LOCATION pIrpSp = IoGetCurrentIrpStackLocation( Irp);
2510     PFILE_OBJECT pFileObject = pIrpSp->FileObject;
2511     AFSFcb *pFcb = NULL;
2512     AFSCcb *pCcb = NULL;
2513     LARGE_INTEGER liSaveAlloc;
2514     LARGE_INTEGER liSaveFileSize;
2515     LARGE_INTEGER liSaveVDL;
2516
2517     pBuffer = (PFILE_ALLOCATION_INFORMATION)Irp->AssociatedIrp.SystemBuffer;
2518
2519     pFcb = (AFSFcb *)pIrpSp->FileObject->FsContext;
2520
2521     pCcb = (AFSCcb *)pIrpSp->FileObject->FsContext2;
2522
2523     //
2524     // save values to put back
2525     //
2526     liSaveAlloc = pFcb->Header.AllocationSize;
2527     liSaveFileSize = pFcb->Header.FileSize;
2528     liSaveVDL = pFcb->Header.ValidDataLength;
2529
2530     if( pFcb->Header.AllocationSize.QuadPart == pBuffer->AllocationSize.QuadPart ||
2531         pIrpSp->Parameters.SetFile.AdvanceOnly)
2532     {
2533         return STATUS_SUCCESS ;
2534     }
2535
2536     if( pFcb->Header.AllocationSize.QuadPart > pBuffer->AllocationSize.QuadPart)
2537     {
2538         //
2539         // Truncating the file
2540         //
2541         if( !MmCanFileBeTruncated( pFileObject->SectionObjectPointer,
2542                                    &pBuffer->AllocationSize))
2543         {
2544
2545             ntStatus = STATUS_USER_MAPPED_FILE ;
2546         }
2547         else
2548         {
2549             //
2550             // If this is a truncation we need to grab the paging IO resource.
2551             //
2552             AFSDbgLogMsg( AFS_SUBSYSTEM_LOCK_PROCESSING,
2553                           AFS_TRACE_LEVEL_VERBOSE,
2554                           "AFSSetAllocationInfo Acquiring Fcb PagingIo lock %08lX EXCL %08lX\n",
2555                           &pFcb->NPFcb->PagingResource,
2556                           PsGetCurrentThread());
2557
2558             AFSAcquireExcl( &pFcb->NPFcb->PagingResource,
2559                             TRUE);
2560
2561             bReleasePaging = TRUE;
2562
2563
2564             pFcb->Header.AllocationSize = pBuffer->AllocationSize;
2565
2566             pFcb->ObjectInformation->AllocationSize = pBuffer->AllocationSize;
2567
2568             //
2569             // Tell Cc that Allocation is moved.
2570             //
2571             bTellCc = TRUE;
2572
2573             if( pFcb->Header.FileSize.QuadPart > pBuffer->AllocationSize.QuadPart)
2574             {
2575                 //
2576                 // We are pulling the EOF back as well so we need to tell
2577                 // the service.
2578                 //
2579                 bTellService = TRUE;
2580
2581                 pFcb->Header.FileSize = pBuffer->AllocationSize;
2582
2583                 pFcb->ObjectInformation->EndOfFile = pBuffer->AllocationSize;
2584             }
2585
2586         }
2587     }
2588     else
2589     {
2590         //
2591         // Tell Cc if allocation is increased.
2592         //
2593         bTellCc = pBuffer->AllocationSize.QuadPart > pFcb->Header.AllocationSize.QuadPart;
2594
2595         pFcb->Header.AllocationSize = pBuffer->AllocationSize;
2596
2597         pFcb->ObjectInformation->AllocationSize = pBuffer->AllocationSize;
2598     }
2599
2600     //
2601     // Now Tell the server if we have to
2602     //
2603     if (bTellService)
2604     {
2605         ntStatus = AFSUpdateFileInformation( &pFcb->ObjectInformation->ParentObjectInformation->FileId,
2606                                              pFcb->ObjectInformation,
2607                                              &pFcb->AuthGroup);
2608     }
2609
2610     if (NT_SUCCESS(ntStatus))
2611     {
2612         //
2613         // Trim extents if we told the service - the update has done an implicit
2614         // trim at the service.
2615         //
2616         if (bTellService)
2617         {
2618             AFSTrimExtents( pFcb,
2619                             &pFcb->Header.FileSize);
2620         }
2621
2622         KeQuerySystemTime( &pFcb->ObjectInformation->ChangeTime);
2623
2624         SetFlag( pFcb->Flags, AFS_FCB_FLAG_FILE_MODIFIED | AFS_FCB_FLAG_UPDATE_CHANGE_TIME);
2625
2626         if (bTellCc &&
2627             CcIsFileCached( pFileObject))
2628         {
2629             CcSetFileSizes( pFileObject,
2630                             (PCC_FILE_SIZES)&pFcb->Header.AllocationSize);
2631         }
2632     }
2633     else
2634     {
2635         //
2636         // Put the saved values back
2637         //
2638         pFcb->Header.ValidDataLength = liSaveVDL;
2639         pFcb->Header.FileSize = liSaveFileSize;
2640         pFcb->Header.AllocationSize = liSaveAlloc;
2641         pFcb->ObjectInformation->EndOfFile = liSaveFileSize;
2642         pFcb->ObjectInformation->AllocationSize = liSaveAlloc;
2643     }
2644
2645     if( bReleasePaging)
2646     {
2647
2648         AFSReleaseResource( &pFcb->NPFcb->PagingResource);
2649     }
2650
2651     return ntStatus;
2652 }
2653
2654 NTSTATUS
2655 AFSSetEndOfFileInfo( IN PIRP Irp,
2656                      IN AFSDirectoryCB *DirectoryCB)
2657 {
2658     NTSTATUS ntStatus = STATUS_SUCCESS;
2659     PFILE_END_OF_FILE_INFORMATION pBuffer;
2660     PIO_STACK_LOCATION pIrpSp = IoGetCurrentIrpStackLocation( Irp);
2661     PFILE_OBJECT pFileObject = pIrpSp->FileObject;
2662     LARGE_INTEGER liSaveSize;
2663     LARGE_INTEGER liSaveVDL;
2664     LARGE_INTEGER liSaveAlloc;
2665     BOOLEAN bModified = FALSE;
2666     BOOLEAN bReleasePaging = FALSE;
2667     BOOLEAN bTruncated = FALSE;
2668     AFSFcb *pFcb = NULL;
2669     AFSCcb *pCcb = NULL;
2670
2671     pFcb = (AFSFcb *)pIrpSp->FileObject->FsContext;
2672
2673     pCcb = (AFSCcb *)pIrpSp->FileObject->FsContext2;
2674
2675     pBuffer = (PFILE_END_OF_FILE_INFORMATION)Irp->AssociatedIrp.SystemBuffer;
2676
2677     liSaveSize = pFcb->Header.FileSize;
2678     liSaveAlloc = pFcb->Header.AllocationSize;
2679     liSaveVDL = pFcb->Header.ValidDataLength;
2680
2681     if( pFcb->Header.FileSize.QuadPart != pBuffer->EndOfFile.QuadPart &&
2682         !pIrpSp->Parameters.SetFile.AdvanceOnly)
2683     {
2684
2685         if( pBuffer->EndOfFile.QuadPart < pFcb->Header.FileSize.QuadPart)
2686         {
2687
2688             // Truncating the file
2689             if( !MmCanFileBeTruncated( pFileObject->SectionObjectPointer,
2690                                        &pBuffer->EndOfFile))
2691             {
2692
2693                 ntStatus = STATUS_USER_MAPPED_FILE;
2694             }
2695             else
2696             {
2697                 //
2698                 // If this is a truncation we need to grab the paging
2699                 // IO resource.
2700                 //
2701                 AFSDbgLogMsg( AFS_SUBSYSTEM_LOCK_PROCESSING,
2702                               AFS_TRACE_LEVEL_VERBOSE,
2703                               "AFSSetAllocationInfo Acquiring Fcb PagingIo lock %08lX EXCL %08lX\n",
2704                               &pFcb->NPFcb->PagingResource,
2705                               PsGetCurrentThread());
2706
2707                 AFSAcquireExcl( &pFcb->NPFcb->PagingResource,
2708                                 TRUE);
2709
2710                 bReleasePaging = TRUE;
2711
2712                 pFcb->Header.AllocationSize = pBuffer->EndOfFile;
2713
2714                 pFcb->Header.FileSize = pBuffer->EndOfFile;
2715
2716                 pFcb->ObjectInformation->EndOfFile = pBuffer->EndOfFile;
2717
2718                 pFcb->ObjectInformation->AllocationSize = pBuffer->EndOfFile;
2719
2720                 if( pFcb->Header.ValidDataLength.QuadPart > pFcb->Header.FileSize.QuadPart)
2721                 {
2722
2723                     pFcb->Header.ValidDataLength = pFcb->Header.FileSize;
2724                 }
2725
2726                 bTruncated = TRUE;
2727
2728                 bModified = TRUE;
2729             }
2730         }
2731         else
2732         {
2733             //
2734             // extending the file, move EOF
2735             //
2736
2737             pFcb->Header.FileSize = pBuffer->EndOfFile;
2738
2739             pFcb->ObjectInformation->EndOfFile = pBuffer->EndOfFile;
2740
2741             if (pFcb->Header.FileSize.QuadPart > pFcb->Header.AllocationSize.QuadPart)
2742             {
2743                 //
2744                 // And Allocation as needed.
2745                 //
2746                 pFcb->Header.AllocationSize = pBuffer->EndOfFile;
2747
2748                 pFcb->ObjectInformation->AllocationSize = pBuffer->EndOfFile;
2749             }
2750
2751             bModified = TRUE;
2752         }
2753     }
2754
2755     if (bModified)
2756     {
2757
2758         KeQuerySystemTime( &pFcb->ObjectInformation->ChangeTime);
2759
2760         SetFlag( pFcb->Flags, AFS_FCB_FLAG_FILE_MODIFIED | AFS_FCB_FLAG_UPDATE_CHANGE_TIME);
2761
2762         //
2763         // Tell the server
2764         //
2765
2766         ntStatus = AFSUpdateFileInformation( &pFcb->ObjectInformation->ParentObjectInformation->FileId,
2767                                              pFcb->ObjectInformation,
2768                                              &pFcb->AuthGroup);
2769
2770         if( NT_SUCCESS(ntStatus))
2771         {
2772             //
2773             // We are now good to go so tell CC.
2774             //
2775             CcSetFileSizes( pFileObject,
2776                             (PCC_FILE_SIZES)&pFcb->Header.AllocationSize);
2777
2778             //
2779             // And give up those extents
2780             //
2781             if( bTruncated)
2782             {
2783
2784                 AFSTrimExtents( pFcb,
2785                                 &pFcb->Header.FileSize);
2786             }
2787         }
2788         else
2789         {
2790             pFcb->Header.ValidDataLength = liSaveVDL;
2791             pFcb->Header.FileSize = liSaveSize;
2792             pFcb->Header.AllocationSize = liSaveAlloc;
2793             pFcb->ObjectInformation->EndOfFile = liSaveSize;
2794             pFcb->ObjectInformation->AllocationSize = liSaveAlloc;
2795         }
2796     }
2797
2798     if( bReleasePaging)
2799     {
2800
2801         AFSReleaseResource( &pFcb->NPFcb->PagingResource);
2802     }
2803
2804     return ntStatus;
2805 }
2806
2807 NTSTATUS
2808 AFSProcessShareSetInfo( IN IRP *Irp,
2809                         IN AFSFcb *Fcb,
2810                         IN AFSCcb *Ccb)
2811 {
2812
2813     NTSTATUS ntStatus = STATUS_SUCCESS;
2814     PIO_STACK_LOCATION pIrpSp = IoGetCurrentIrpStackLocation( Irp);
2815     ULONG ulOutputBufferLen = 0, ulInputBufferLen;
2816     FILE_INFORMATION_CLASS ulFileInformationClass;
2817     void *pPipeInfo = NULL;
2818
2819     __Enter
2820     {
2821         ulFileInformationClass = pIrpSp->Parameters.SetFile.FileInformationClass;
2822
2823         AFSDbgLogMsg( AFS_SUBSYSTEM_PIPE_PROCESSING,
2824                       AFS_TRACE_LEVEL_VERBOSE,
2825                       "AFSProcessShareSetInfo On pipe %wZ Class %08lX\n",
2826                       &Ccb->DirectoryCB->NameInformation.FileName,
2827                       ulFileInformationClass);
2828
2829         pPipeInfo = AFSLockSystemBuffer( Irp,
2830                                          pIrpSp->Parameters.SetFile.Length);
2831
2832         if( pPipeInfo == NULL)
2833         {
2834
2835             AFSDbgLogMsg( AFS_SUBSYSTEM_PIPE_PROCESSING,
2836                           AFS_TRACE_LEVEL_ERROR,
2837                           "AFSProcessShareSetInfo Failed to lock buffer on pipe %wZ\n",
2838                           &Ccb->DirectoryCB->NameInformation.FileName);
2839
2840             try_return( ntStatus = STATUS_INSUFFICIENT_RESOURCES);
2841         }
2842
2843         //
2844         // Send the request to the service
2845         //
2846
2847         ntStatus = AFSNotifySetPipeInfo( Ccb,
2848                                          (ULONG)ulFileInformationClass,
2849                                          pIrpSp->Parameters.SetFile.Length,
2850                                          pPipeInfo);
2851
2852         if( !NT_SUCCESS( ntStatus))
2853         {
2854
2855             AFSDbgLogMsg( AFS_SUBSYSTEM_PIPE_PROCESSING,
2856                           AFS_TRACE_LEVEL_ERROR,
2857                           "AFSProcessShareSetInfo Failed to send request to service on pipe %wZ Status %08lX\n",
2858                           &Ccb->DirectoryCB->NameInformation.FileName,
2859                           ntStatus);
2860
2861             try_return( ntStatus);
2862         }
2863
2864         AFSDbgLogMsg( AFS_SUBSYSTEM_PIPE_PROCESSING,
2865                       AFS_TRACE_LEVEL_VERBOSE,
2866                       "AFSProcessShareSetInfo Completed request on pipe %wZ Class %08lX\n",
2867                       &Ccb->DirectoryCB->NameInformation.FileName,
2868                       ulFileInformationClass);
2869
2870 try_exit:
2871
2872         NOTHING;
2873     }
2874
2875     return ntStatus;
2876 }
2877
2878 NTSTATUS
2879 AFSProcessShareQueryInfo( IN IRP *Irp,
2880                           IN AFSFcb *Fcb,
2881                           IN AFSCcb *Ccb)
2882 {
2883
2884     NTSTATUS ntStatus = STATUS_SUCCESS;
2885     PIO_STACK_LOCATION pIrpSp = IoGetCurrentIrpStackLocation( Irp);
2886     ULONG ulOutputBufferLen = 0, ulInputBufferLen;
2887     FILE_INFORMATION_CLASS ulFileInformationClass;
2888     void *pPipeInfo = NULL;
2889
2890     __Enter
2891     {
2892
2893         ulFileInformationClass = pIrpSp->Parameters.QueryFile.FileInformationClass;
2894
2895         AFSDbgLogMsg( AFS_SUBSYSTEM_PIPE_PROCESSING,
2896                       AFS_TRACE_LEVEL_VERBOSE,
2897                       "AFSProcessShareQueryInfo On pipe %wZ Class %08lX\n",
2898                       &Ccb->DirectoryCB->NameInformation.FileName,
2899                       ulFileInformationClass);
2900
2901         pPipeInfo = AFSLockSystemBuffer( Irp,
2902                                          pIrpSp->Parameters.QueryFile.Length);
2903
2904         if( pPipeInfo == NULL)
2905         {
2906
2907             AFSDbgLogMsg( AFS_SUBSYSTEM_PIPE_PROCESSING,
2908                           AFS_TRACE_LEVEL_ERROR,
2909                           "AFSProcessShareQueryInfo Failed to lock buffer on pipe %wZ\n",
2910                           &Ccb->DirectoryCB->NameInformation.FileName);
2911
2912             try_return( ntStatus = STATUS_INSUFFICIENT_RESOURCES);
2913         }
2914
2915         //
2916         // Send the request to the service
2917         //
2918
2919         ntStatus = AFSNotifyQueryPipeInfo( Ccb,
2920                                            (ULONG)ulFileInformationClass,
2921                                            pIrpSp->Parameters.QueryFile.Length,
2922                                            pPipeInfo,
2923                                            (ULONG *)&Irp->IoStatus.Information);
2924
2925         if( !NT_SUCCESS( ntStatus))
2926         {
2927
2928             AFSDbgLogMsg( AFS_SUBSYSTEM_PIPE_PROCESSING,
2929                           AFS_TRACE_LEVEL_ERROR,
2930                           "AFSProcessShareQueryInfo Failed to send request to service on pipe %wZ Status %08lX\n",
2931                           &Ccb->DirectoryCB->NameInformation.FileName,
2932                           ntStatus);
2933
2934             try_return( ntStatus);
2935         }
2936
2937         AFSDbgLogMsg( AFS_SUBSYSTEM_PIPE_PROCESSING,
2938                       AFS_TRACE_LEVEL_VERBOSE,
2939                       "AFSProcessShareQueryInfo Completed request on pipe %wZ Class %08lX\n",
2940                       &Ccb->DirectoryCB->NameInformation.FileName,
2941                       ulFileInformationClass);
2942
2943 try_exit:
2944
2945         NOTHING;
2946     }
2947
2948     return ntStatus;
2949 }
2950
2951 NTSTATUS
2952 AFSProcessPIOCtlQueryInfo( IN IRP *Irp,
2953                            IN AFSFcb *Fcb,
2954                            IN AFSCcb *Ccb,
2955                            IN OUT LONG *Length)
2956 {
2957
2958     NTSTATUS ntStatus = STATUS_SUCCESS;
2959     PIO_STACK_LOCATION pIrpSp = IoGetCurrentIrpStackLocation( Irp);
2960     FILE_INFORMATION_CLASS ulFileInformationClass;
2961
2962     __Enter
2963     {
2964
2965         ulFileInformationClass = pIrpSp->Parameters.QueryFile.FileInformationClass;
2966
2967         switch( ulFileInformationClass)
2968         {
2969
2970             case FileBasicInformation:
2971             {
2972
2973                 if ( *Length >= sizeof( FILE_BASIC_INFORMATION))
2974                 {
2975                     PFILE_BASIC_INFORMATION pBasic = (PFILE_BASIC_INFORMATION)Irp->AssociatedIrp.SystemBuffer;
2976
2977                     pBasic->CreationTime.QuadPart = 0;
2978                     pBasic->LastAccessTime.QuadPart = 0;
2979                     pBasic->ChangeTime.QuadPart = 0;
2980                     pBasic->LastWriteTime.QuadPart = 0;
2981                     pBasic->FileAttributes = FILE_ATTRIBUTE_SYSTEM;
2982
2983                     *Length -= sizeof( FILE_BASIC_INFORMATION);
2984                 }
2985                 else
2986                 {
2987                     ntStatus = STATUS_BUFFER_OVERFLOW;
2988                 }
2989
2990                 break;
2991             }
2992
2993             case FileStandardInformation:
2994             {
2995
2996                 if ( *Length >= sizeof( FILE_STANDARD_INFORMATION))
2997                 {
2998                     PFILE_STANDARD_INFORMATION pStandard = (PFILE_STANDARD_INFORMATION)Irp->AssociatedIrp.SystemBuffer;
2999
3000                     pStandard->NumberOfLinks = 1;
3001                     pStandard->DeletePending = 0;
3002                     pStandard->AllocationSize.QuadPart = 4096;
3003                     pStandard->EndOfFile.QuadPart = 4096;
3004                     pStandard->Directory = 0;
3005
3006                     *Length -= sizeof( FILE_STANDARD_INFORMATION);
3007                 }
3008                 else
3009                 {
3010                     ntStatus = STATUS_BUFFER_OVERFLOW;
3011                 }
3012
3013                 break;
3014             }
3015
3016             case FileNameInformation:
3017             {
3018
3019                 ULONG ulCopyLength = 0;
3020                 AFSFcb *pFcb = NULL;
3021                 AFSCcb *pCcb = NULL;
3022                 USHORT usFullNameLength = 0;
3023                 PFILE_NAME_INFORMATION pNameInfo = (PFILE_NAME_INFORMATION)Irp->AssociatedIrp.SystemBuffer;
3024                 UNICODE_STRING uniName;
3025
3026                 pFcb = (AFSFcb *)pIrpSp->FileObject->FsContext;
3027                 pCcb = (AFSCcb *)pIrpSp->FileObject->FsContext2;
3028
3029                 if( *Length < FIELD_OFFSET( FILE_NAME_INFORMATION, FileName))
3030                 {
3031                     ntStatus = STATUS_BUFFER_TOO_SMALL;
3032                     break;
3033                 }
3034
3035                 RtlZeroMemory( pNameInfo,
3036                                *Length);
3037
3038                 usFullNameLength = sizeof( WCHAR) +
3039                                             AFSServerName.Length +
3040                                             pCcb->FullFileName.Length;
3041
3042                 if( *Length >= (LONG)(FIELD_OFFSET( FILE_NAME_INFORMATION, FileName) + (LONG)usFullNameLength))
3043                 {
3044                     ulCopyLength = (LONG)usFullNameLength;
3045                 }
3046                 else
3047                 {
3048                     ulCopyLength = *Length - FIELD_OFFSET( FILE_NAME_INFORMATION, FileName);
3049                     ntStatus = STATUS_BUFFER_OVERFLOW;
3050                 }
3051
3052                 pNameInfo->FileNameLength = (ULONG)usFullNameLength;
3053
3054                 *Length -= FIELD_OFFSET( FILE_NAME_INFORMATION, FileName);
3055
3056                 if( ulCopyLength > 0)
3057                 {
3058
3059                     pNameInfo->FileName[ 0] = L'\\';
3060                     ulCopyLength -= sizeof( WCHAR);
3061
3062                     *Length -= sizeof( WCHAR);
3063
3064                     if( ulCopyLength >= AFSServerName.Length)
3065                     {
3066
3067                         RtlCopyMemory( &pNameInfo->FileName[ 1],
3068                                        AFSServerName.Buffer,
3069                                        AFSServerName.Length);
3070
3071                         ulCopyLength -= AFSServerName.Length;
3072                         *Length -= AFSServerName.Length;
3073
3074                         if( ulCopyLength >= pCcb->FullFileName.Length)
3075                         {
3076
3077                             RtlCopyMemory( &pNameInfo->FileName[ 1 + (AFSServerName.Length/sizeof( WCHAR))],
3078                                            pCcb->FullFileName.Buffer,
3079                                            pCcb->FullFileName.Length);
3080
3081                             ulCopyLength -= pCcb->FullFileName.Length;
3082                             *Length -= pCcb->FullFileName.Length;
3083
3084                             uniName.Length = (USHORT)pNameInfo->FileNameLength;
3085                             uniName.MaximumLength = uniName.Length;
3086                             uniName.Buffer = pNameInfo->FileName;
3087                         }
3088                         else
3089                         {
3090
3091                             RtlCopyMemory( &pNameInfo->FileName[ 1 + (AFSServerName.Length/sizeof( WCHAR))],
3092                                            pCcb->FullFileName.Buffer,
3093                                            ulCopyLength);
3094
3095                             *Length -= ulCopyLength;
3096
3097                             uniName.Length = (USHORT)(sizeof( WCHAR) + AFSServerName.Length + ulCopyLength);
3098                             uniName.MaximumLength = uniName.Length;
3099                             uniName.Buffer = pNameInfo->FileName;
3100                         }
3101
3102                         AFSDbgLogMsg( AFS_SUBSYSTEM_PIOCTL_PROCESSING,
3103                                       AFS_TRACE_LEVEL_VERBOSE,
3104                                       "AFSProcessPIOCtlQueryInfo (FileNameInformation) Returning %wZ\n",
3105                                       &uniName);
3106                     }
3107                 }
3108
3109                 break;
3110             }
3111
3112             case FileInternalInformation:
3113             {
3114
3115                 PFILE_INTERNAL_INFORMATION pInternalInfo = (PFILE_INTERNAL_INFORMATION)Irp->AssociatedIrp.SystemBuffer;
3116
3117                 if( *Length >= sizeof( FILE_INTERNAL_INFORMATION))
3118                 {
3119
3120                     pInternalInfo->IndexNumber.HighPart = 0;
3121
3122                     pInternalInfo->IndexNumber.LowPart = 0;
3123
3124                     *Length -= sizeof( FILE_INTERNAL_INFORMATION);
3125                 }
3126                 else
3127                 {
3128
3129                     ntStatus = STATUS_BUFFER_TOO_SMALL;
3130                 }
3131
3132                 break;
3133             }
3134
3135             default:
3136             {
3137                 ntStatus = STATUS_INVALID_PARAMETER;
3138
3139                 AFSDbgLogMsg( AFS_SUBSYSTEM_PIOCTL_PROCESSING,
3140                               AFS_TRACE_LEVEL_WARNING,
3141                               "AFSProcessPIOCtlQueryInfo Not handling request %08lX\n",
3142                               ulFileInformationClass);
3143
3144                 break;
3145             }
3146         }
3147     }
3148
3149     return ntStatus;
3150 }
3151