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