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