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