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