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