Windows: FileStandardInfo 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                 // Reduce the Link count in the object information block
1918                 // to correspond with the deletion of the directory entry.
1919                 //
1920
1921                 pFcb->ObjectInformation->Links--;
1922
1923                 //
1924                 // Check if this is a directory that there are not currently other opens
1925                 //
1926
1927                 if( pFcb->ObjectInformation->Specific.Directory.ChildOpenHandleCount > 0)
1928                 {
1929
1930                     AFSDbgTrace(( AFS_SUBSYSTEM_FILE_PROCESSING,
1931                                   AFS_TRACE_LEVEL_ERROR,
1932                                   "AFSSetDispositionInfo Attempt to delete directory %wZ with open %u handles\n",
1933                                   &DirectoryCB->NameInformation.FileName,
1934                                   pFcb->ObjectInformation->Specific.Directory.ChildOpenHandleCount));
1935
1936                     try_return( ntStatus = STATUS_DIRECTORY_NOT_EMPTY);
1937                 }
1938
1939                 //
1940                 // Make sure the directory is enumerated before checking to see if it is empty.
1941                 //
1942
1943                 if( !BooleanFlagOn( pFcb->ObjectInformation->Flags, AFS_OBJECT_FLAGS_DIRECTORY_ENUMERATED))
1944                 {
1945
1946                     AFSAcquireExcl( pFcb->ObjectInformation->Specific.Directory.DirectoryNodeHdr.TreeLock,
1947                                     TRUE);
1948
1949                     if( !BooleanFlagOn( pFcb->ObjectInformation->Flags, AFS_OBJECT_FLAGS_DIRECTORY_ENUMERATED))
1950                     {
1951
1952                         AFSDbgTrace(( AFS_SUBSYSTEM_FILE_PROCESSING,
1953                                       AFS_TRACE_LEVEL_VERBOSE,
1954                                       "AFSSetDispositionInfo Enumerating parent FID %08lX-%08lX-%08lX-%08lX\n",
1955                                       pFcb->ObjectInformation->FileId.Cell,
1956                                       pFcb->ObjectInformation->FileId.Volume,
1957                                       pFcb->ObjectInformation->FileId.Vnode,
1958                                       pFcb->ObjectInformation->FileId.Unique));
1959
1960                         ntStatus = AFSEnumerateDirectory( &pCcb->AuthGroup,
1961                                                           pFcb->ObjectInformation,
1962                                                           TRUE);
1963
1964                         if( !NT_SUCCESS( ntStatus))
1965                         {
1966
1967                             AFSReleaseResource( pFcb->ObjectInformation->Specific.Directory.DirectoryNodeHdr.TreeLock);
1968
1969                             AFSDbgTrace(( AFS_SUBSYSTEM_FILE_PROCESSING,
1970                                           AFS_TRACE_LEVEL_ERROR,
1971                                           "AFSSetDispositionInfo Failed to enumerate parent FID %08lX-%08lX-%08lX-%08lX Status %08lX\n",
1972                                           pFcb->ObjectInformation->FileId.Cell,
1973                                           pFcb->ObjectInformation->FileId.Volume,
1974                                           pFcb->ObjectInformation->FileId.Vnode,
1975                                           pFcb->ObjectInformation->FileId.Unique,
1976                                           ntStatus));
1977
1978                             try_return( ntStatus);
1979                         }
1980                     }
1981
1982                     AFSReleaseResource( pFcb->ObjectInformation->Specific.Directory.DirectoryNodeHdr.TreeLock);
1983                 }
1984
1985                 if( !AFSIsDirectoryEmptyForDelete( pFcb))
1986                 {
1987
1988                     AFSDbgTrace(( AFS_SUBSYSTEM_FILE_PROCESSING,
1989                                   AFS_TRACE_LEVEL_ERROR,
1990                                   "AFSSetDispositionInfo Attempt to delete non-empty directory %wZ\n",
1991                                   &DirectoryCB->NameInformation.FileName));
1992
1993                     try_return( ntStatus = STATUS_DIRECTORY_NOT_EMPTY);
1994                 }
1995
1996                 AFSDbgTrace(( AFS_SUBSYSTEM_FILE_PROCESSING,
1997                               AFS_TRACE_LEVEL_VERBOSE,
1998                               "AFSSetDispositionInfo Setting PENDING_DELETE on DirEntry  %p Name %wZ\n",
1999                               DirectoryCB,
2000                               &DirectoryCB->NameInformation.FileName));
2001
2002                 SetFlag( pCcb->DirectoryCB->Flags, AFS_DIR_ENTRY_PENDING_DELETE);
2003             }
2004             else if( pFcb->Header.NodeTypeCode == AFS_FILE_FCB)
2005             {
2006                 BOOLEAN bMmFlushed;
2007
2008                 AFSDbgTrace(( AFS_SUBSYSTEM_LOCK_PROCESSING,
2009                               AFS_TRACE_LEVEL_VERBOSE,
2010                               "AFSSetDispositionInfo Acquiring Fcb lock %p EXCL %08lX\n",
2011                               &pFcb->NPFcb->Resource,
2012                               PsGetCurrentThread()));
2013
2014                 AFSAcquireExcl( &pFcb->NPFcb->Resource,
2015                                 TRUE);
2016
2017                 AFSDbgTrace(( AFS_SUBSYSTEM_LOCK_PROCESSING|AFS_SUBSYSTEM_SECTION_OBJECT,
2018                               AFS_TRACE_LEVEL_VERBOSE,
2019                               "AFSSetDispositionInfo Acquiring Fcb SectionObject lock %p EXCL %08lX\n",
2020                               &pFcb->NPFcb->SectionObjectResource,
2021                               PsGetCurrentThread()));
2022
2023                 AFSAcquireExcl( &pFcb->NPFcb->SectionObjectResource,
2024                                 TRUE);
2025
2026                 __try
2027                 {
2028
2029                     //
2030                     // Attempt to flush any outstanding data
2031                     //
2032
2033                     bMmFlushed = MmFlushImageSection( &pFcb->NPFcb->SectionObjectPointers,
2034                                                       MmFlushForDelete);
2035
2036                     if ( bMmFlushed)
2037                     {
2038
2039                         //
2040                         // Set PENDING_DELETE before CcPurgeCacheSection to avoid a
2041                         // deadlock with Trend Micro's Enterprise anti-virus product
2042                         // which attempts to open the file which is being deleted.
2043                         //
2044
2045                         AFSDbgTrace(( AFS_SUBSYSTEM_FILE_PROCESSING,
2046                                       AFS_TRACE_LEVEL_VERBOSE,
2047                                       "AFSSetDispositionInfo Setting PENDING_DELETE on DirEntry %p Name %wZ\n",
2048                                       DirectoryCB,
2049                                       &DirectoryCB->NameInformation.FileName));
2050
2051                         SetFlag( pCcb->DirectoryCB->Flags, AFS_DIR_ENTRY_PENDING_DELETE);
2052
2053                         //
2054                         // Purge the cache as well
2055                         //
2056
2057                         if( pFcb->NPFcb->SectionObjectPointers.DataSectionObject != NULL)
2058                         {
2059
2060                             if ( !CcPurgeCacheSection( &pFcb->NPFcb->SectionObjectPointers,
2061                                                        NULL,
2062                                                        0,
2063                                                        TRUE))
2064                             {
2065
2066                                 SetFlag( pFcb->Flags, AFS_FCB_FLAG_PURGE_ON_CLOSE);
2067                             }
2068                         }
2069                     }
2070                 }
2071                 __except( EXCEPTION_EXECUTE_HANDLER)
2072                 {
2073
2074                     bMmFlushed = FALSE;
2075
2076                     ntStatus = GetExceptionCode();
2077
2078                     AFSDbgTrace(( 0,
2079                                   0,
2080                                   "EXCEPTION - AFSSetDispositionInfo MmFlushImageSection failed FID %08lX-%08lX-%08lX-%08lX Status 0x%08lX\n",
2081                                   pFcb->ObjectInformation->FileId.Cell,
2082                                   pFcb->ObjectInformation->FileId.Volume,
2083                                   pFcb->ObjectInformation->FileId.Vnode,
2084                                   pFcb->ObjectInformation->FileId.Unique,
2085                                   ntStatus));
2086                 }
2087
2088                 AFSDbgTrace(( AFS_SUBSYSTEM_LOCK_PROCESSING|AFS_SUBSYSTEM_SECTION_OBJECT,
2089                               AFS_TRACE_LEVEL_VERBOSE,
2090                               "AFSSetDispositionInfo Releasing Fcb SectionObject lock %p EXCL %08lX\n",
2091                               &pFcb->NPFcb->SectionObjectResource,
2092                               PsGetCurrentThread()));
2093
2094                 AFSReleaseResource( &pFcb->NPFcb->SectionObjectResource);
2095
2096                 AFSDbgTrace(( AFS_SUBSYSTEM_LOCK_PROCESSING,
2097                               AFS_TRACE_LEVEL_VERBOSE,
2098                               "AFSSetDispositionInfo Releasing Fcb lock %p EXCL %08lX\n",
2099                               &pFcb->NPFcb->Resource,
2100                               PsGetCurrentThread()));
2101
2102                 AFSReleaseResource( &pFcb->NPFcb->Resource);
2103
2104                 if ( !bMmFlushed)
2105                 {
2106
2107                     AFSDbgTrace(( AFS_SUBSYSTEM_FILE_PROCESSING,
2108                                   AFS_TRACE_LEVEL_ERROR,
2109                                   "AFSSetDispositionInfo Failed to flush image section for delete Entry %wZ\n",
2110                                   &DirectoryCB->NameInformation.FileName));
2111
2112                     try_return( ntStatus = STATUS_CANNOT_DELETE);
2113                 }
2114             }
2115             else if( pFcb->Header.NodeTypeCode == AFS_SYMBOLIC_LINK_FCB ||
2116                      pFcb->Header.NodeTypeCode == AFS_MOUNT_POINT_FCB ||
2117                      pFcb->Header.NodeTypeCode == AFS_DFS_LINK_FCB ||
2118                      pFcb->Header.NodeTypeCode == AFS_INVALID_FCB)
2119             {
2120
2121                 AFSDbgTrace(( AFS_SUBSYSTEM_FILE_PROCESSING,
2122                               AFS_TRACE_LEVEL_VERBOSE,
2123                               "AFSSetDispositionInfo Setting PENDING_DELETE on DirEntry %p Name %wZ\n",
2124                               DirectoryCB,
2125                               &DirectoryCB->NameInformation.FileName));
2126
2127                 SetFlag( pCcb->DirectoryCB->Flags, AFS_DIR_ENTRY_PENDING_DELETE);
2128             }
2129         }
2130         else
2131         {
2132
2133             ClearFlag( pCcb->DirectoryCB->Flags, AFS_DIR_ENTRY_PENDING_DELETE);
2134         }
2135
2136         //
2137         // OK, should be good to go, set the flag in the file object
2138         //
2139
2140         pIrpSp->FileObject->DeletePending = pBuffer->DeleteFile;
2141
2142 try_exit:
2143
2144         NOTHING;
2145     }
2146
2147     return ntStatus;
2148 }
2149
2150 NTSTATUS
2151 AFSSetFileLinkInfo( IN PIRP Irp)
2152 {
2153
2154     NTSTATUS ntStatus = STATUS_SUCCESS;
2155     AFSDeviceExt *pDeviceExt = (AFSDeviceExt *)AFSRDRDeviceObject->DeviceExtension;
2156     PIO_STACK_LOCATION pIrpSp = IoGetCurrentIrpStackLocation( Irp);
2157     PFILE_LINK_INFORMATION pFileLinkInfo = NULL;
2158     PFILE_OBJECT pSrcFileObj = NULL;
2159     PFILE_OBJECT pTargetFileObj = pIrpSp->Parameters.SetFile.FileObject;
2160     AFSFcb *pSrcFcb = NULL, *pTargetDcb = NULL;
2161     AFSCcb *pSrcCcb = NULL, *pTargetDirCcb = NULL;
2162     AFSObjectInfoCB *pSrcObject = NULL;
2163     AFSObjectInfoCB *pSrcParentObject = NULL, *pTargetParentObject = NULL;
2164     UNICODE_STRING uniSourceName, uniTargetName;
2165     UNICODE_STRING uniFullTargetName, uniTargetParentName;
2166     BOOLEAN bCommonParent = FALSE;
2167     AFSDirectoryCB *pTargetDirEntry = NULL;
2168     AFSDirectoryCB *pNewTargetDirEntry = NULL;
2169     ULONG ulTargetCRC;
2170     BOOLEAN bTargetEntryExists = FALSE;
2171     LONG lCount;
2172     BOOLEAN bReleaseTargetDirLock = FALSE;
2173     ULONG ulNotificationAction = 0, ulNotifyFilter = 0;
2174
2175     __Enter
2176     {
2177
2178         pSrcFileObj = pIrpSp->FileObject;
2179
2180         pSrcFcb = (AFSFcb *)pSrcFileObj->FsContext;
2181         pSrcCcb = (AFSCcb *)pSrcFileObj->FsContext2;
2182
2183         pSrcObject = pSrcFcb->ObjectInformation;
2184
2185         if ( BooleanFlagOn( pSrcObject->Flags, AFS_OBJECT_FLAGS_PARENT_FID))
2186         {
2187
2188             pSrcParentObject = AFSFindObjectInfo( pSrcObject->VolumeCB,
2189                                                   &pSrcObject->ParentFileId,
2190                                                   TRUE);
2191         }
2192
2193         if( pSrcParentObject == NULL)
2194         {
2195
2196             AFSDbgTrace(( AFS_SUBSYSTEM_FILE_PROCESSING,
2197                           AFS_TRACE_LEVEL_ERROR,
2198                           "AFSSetFileLinkInfo Unable to resolve SrcParentObject (INVALID_PARAMETER)\n"));
2199
2200             ASSERT( FALSE);
2201
2202             try_return( ntStatus = STATUS_INVALID_PARAMETER);
2203         }
2204
2205         pFileLinkInfo = (PFILE_LINK_INFORMATION)Irp->AssociatedIrp.SystemBuffer;
2206
2207         //
2208         // Perform some basic checks to ensure FS integrity
2209         //
2210
2211         if( pSrcFcb->Header.NodeTypeCode != AFS_FILE_FCB)
2212         {
2213
2214             AFSDbgTrace(( AFS_SUBSYSTEM_FILE_PROCESSING,
2215                           AFS_TRACE_LEVEL_ERROR,
2216                           "AFSSetFileLinkInfo Attempt to non-file (INVALID_PARAMETER)\n"));
2217
2218             try_return( ntStatus = STATUS_INVALID_PARAMETER);
2219         }
2220
2221         if( pTargetFileObj == NULL)
2222         {
2223
2224             if ( pFileLinkInfo->RootDirectory)
2225             {
2226
2227                 //
2228                 // The target directory is provided by HANDLE
2229                 // RootDirectory is only set when the target directory is not the same
2230                 // as the source directory.
2231                 //
2232                 // AFS only supports hard links within a single directory.
2233                 //
2234                 // The IOManager should translate any Handle to a FileObject for us.
2235                 // However, the failure to receive a FileObject is treated as a fatal
2236                 // error.
2237                 //
2238
2239                 AFSDbgTrace(( AFS_SUBSYSTEM_FILE_PROCESSING,
2240                               AFS_TRACE_LEVEL_ERROR,
2241                               "AFSSetFileLinkInfo Attempt to link %wZ to alternate directory by handle INVALID_PARAMETER\n",
2242                               &pSrcCcb->DirectoryCB->NameInformation.FileName));
2243
2244                 try_return( ntStatus = STATUS_INVALID_PARAMETER);
2245             }
2246             else
2247             {
2248
2249                 uniFullTargetName.Length = (USHORT)pFileLinkInfo->FileNameLength;
2250
2251                 uniFullTargetName.Buffer = (PWSTR)&pFileLinkInfo->FileName;
2252
2253                 AFSRetrieveFinalComponent( &uniFullTargetName,
2254                                            &uniTargetName);
2255
2256                 AFSRetrieveParentPath( &uniFullTargetName,
2257                                        &uniTargetParentName);
2258
2259                 if ( uniTargetParentName.Length == 0)
2260                 {
2261
2262                     //
2263                     // This is a simple rename. Here the target directory is the same as the source parent directory
2264                     // and the name is retrieved from the system buffer information
2265                     //
2266
2267                     pTargetParentObject = pSrcParentObject;
2268                 }
2269                 else
2270                 {
2271                     //
2272                     // uniTargetParentName contains the directory the renamed object
2273                     // will be moved to.  Must obtain the TargetParentObject.
2274                     //
2275
2276                     AFSDbgTrace(( AFS_SUBSYSTEM_FILE_PROCESSING,
2277                                   AFS_TRACE_LEVEL_ERROR,
2278                                   "AFSSetFileLinkInfo Attempt to link  %wZ to alternate directory %wZ (NOT_SAME_DEVICE)\n",
2279                                   &pSrcCcb->DirectoryCB->NameInformation.FileName,
2280                                   &uniFullTargetName));
2281
2282                     try_return( ntStatus = STATUS_NOT_SAME_DEVICE);
2283                 }
2284             }
2285
2286             pTargetDcb = pTargetParentObject->Fcb;
2287         }
2288         else
2289         {
2290
2291             //
2292             // So here we have the target directory taken from the targetfile object
2293             //
2294
2295             pTargetDcb = (AFSFcb *)pTargetFileObj->FsContext;
2296
2297             pTargetDirCcb = (AFSCcb *)pTargetFileObj->FsContext2;
2298
2299             pTargetParentObject = (AFSObjectInfoCB *)pTargetDcb->ObjectInformation;
2300
2301             //
2302             // Grab the target name which we setup in the IRP_MJ_CREATE handler. By how we set this up
2303             // it is only the target component of the rename operation
2304             //
2305
2306             uniTargetName = *((PUNICODE_STRING)&pTargetFileObj->FileName);
2307         }
2308
2309         //
2310         // The quick check to see if they are self linking.
2311         // Do the names match? Only do this where the parent directories are
2312         // the same
2313         //
2314
2315         if( pTargetParentObject == pSrcParentObject)
2316         {
2317
2318             if( FsRtlAreNamesEqual( &uniTargetName,
2319                                     &uniSourceName,
2320                                     FALSE,
2321                                     NULL))
2322             {
2323                 try_return( ntStatus = STATUS_SUCCESS);
2324             }
2325
2326             bCommonParent = TRUE;
2327         }
2328         else
2329         {
2330
2331             //
2332             // We do not allow cross-volume hard links
2333             //
2334
2335             if( pTargetParentObject->VolumeCB != pSrcObject->VolumeCB)
2336             {
2337
2338                 AFSDbgTrace(( AFS_SUBSYSTEM_FILE_PROCESSING,
2339                               AFS_TRACE_LEVEL_ERROR,
2340                               "AFSSetFileLinkInfo Attempt to link to different volume %wZ\n",
2341                               &pSrcCcb->DirectoryCB->NameInformation.FileName));
2342
2343                 try_return( ntStatus = STATUS_NOT_SAME_DEVICE);
2344             }
2345         }
2346
2347         ulTargetCRC = AFSGenerateCRC( &uniTargetName,
2348                                       FALSE);
2349
2350         AFSAcquireExcl( pTargetParentObject->Specific.Directory.DirectoryNodeHdr.TreeLock,
2351                         TRUE);
2352
2353         bReleaseTargetDirLock = TRUE;
2354
2355         AFSLocateCaseSensitiveDirEntry( pTargetParentObject->Specific.Directory.DirectoryNodeHdr.CaseSensitiveTreeHead,
2356                                         ulTargetCRC,
2357                                         &pTargetDirEntry);
2358
2359         if( pTargetDirEntry == NULL)
2360         {
2361
2362             //
2363             // Missed so perform a case insensitive lookup
2364             //
2365
2366             ulTargetCRC = AFSGenerateCRC( &uniTargetName,
2367                                           TRUE);
2368
2369             AFSLocateCaseInsensitiveDirEntry( pTargetParentObject->Specific.Directory.DirectoryNodeHdr.CaseInsensitiveTreeHead,
2370                                               ulTargetCRC,
2371                                               &pTargetDirEntry);
2372         }
2373
2374         if ( !BooleanFlagOn( pDeviceExt->DeviceFlags, AFS_DEVICE_FLAG_DISABLE_SHORTNAMES) &&
2375              pTargetDirEntry == NULL && RtlIsNameLegalDOS8Dot3( &uniTargetName,
2376                                                                 NULL,
2377                                                                 NULL))
2378         {
2379             //
2380             // Try the short name
2381             //
2382             AFSLocateShortNameDirEntry( pTargetParentObject->Specific.Directory.ShortNameTree,
2383                                         ulTargetCRC,
2384                                         &pTargetDirEntry);
2385         }
2386
2387         //
2388         // Increment our ref count on the dir entry
2389         //
2390
2391         if( pTargetDirEntry != NULL)
2392         {
2393
2394             ASSERT( BooleanFlagOn( pTargetDirEntry->ObjectInformation->Flags, AFS_OBJECT_FLAGS_PARENT_FID) &&
2395                     AFSIsEqualFID( &pTargetParentObject->FileId, &pTargetDirEntry->ObjectInformation->ParentFileId));
2396
2397             lCount = InterlockedIncrement( &pTargetDirEntry->DirOpenReferenceCount);
2398
2399             AFSDbgTrace(( AFS_SUBSYSTEM_DIRENTRY_REF_COUNTING,
2400                           AFS_TRACE_LEVEL_VERBOSE,
2401                           "AFSSetFileLinkInfo Increment count on %wZ DE %p Ccb %p Cnt %d\n",
2402                           &pTargetDirEntry->NameInformation.FileName,
2403                           pTargetDirEntry,
2404                           pSrcCcb,
2405                           lCount));
2406
2407             ASSERT( lCount >= 0);
2408
2409             if( !pFileLinkInfo->ReplaceIfExists)
2410             {
2411
2412                 AFSDbgTrace(( AFS_SUBSYSTEM_FILE_PROCESSING,
2413                               AFS_TRACE_LEVEL_ERROR,
2414                               "AFSSetFileLinkInfo Attempt to link with target collision %wZ Target %wZ\n",
2415                               &pSrcCcb->DirectoryCB->NameInformation.FileName,
2416                               &pTargetDirEntry->NameInformation.FileName));
2417
2418                 try_return( ntStatus = STATUS_OBJECT_NAME_COLLISION);
2419             }
2420
2421             AFSDbgTrace(( AFS_SUBSYSTEM_FILE_PROCESSING | AFS_SUBSYSTEM_DIRENTRY_REF_COUNTING,
2422                           AFS_TRACE_LEVEL_ERROR,
2423                           "AFSSetFileLinkInfo Target %wZ exists DE %p Count %d, performing delete of target\n",
2424                           &pTargetDirEntry->NameInformation.FileName,
2425                           pTargetDirEntry,
2426                           lCount));
2427
2428             //
2429             // Pull the directory entry from the parent
2430             //
2431
2432             AFSRemoveDirNodeFromParent( pTargetParentObject,
2433                                         pTargetDirEntry,
2434                                         FALSE);
2435
2436             bTargetEntryExists = TRUE;
2437         }
2438         else
2439         {
2440             AFSDbgTrace(( AFS_SUBSYSTEM_FILE_PROCESSING,
2441                           AFS_TRACE_LEVEL_VERBOSE,
2442                           "AFSSetFileLinkInfo Target does NOT exist, normal linking\n"));
2443         }
2444
2445         //
2446         // OK, this is a simple rename. Issue the rename
2447         // request to the service.
2448         //
2449
2450         ntStatus = AFSNotifyHardLink( pSrcObject,
2451                                       &pSrcCcb->AuthGroup,
2452                                       pSrcParentObject,
2453                                       pTargetDcb->ObjectInformation,
2454                                       pSrcCcb->DirectoryCB,
2455                                       &uniTargetName,
2456                                       pFileLinkInfo->ReplaceIfExists,
2457                                       &pNewTargetDirEntry);
2458
2459         if( ntStatus != STATUS_REPARSE &&
2460             !NT_SUCCESS( ntStatus))
2461         {
2462
2463             AFSDbgTrace(( AFS_SUBSYSTEM_FILE_PROCESSING,
2464                           AFS_TRACE_LEVEL_ERROR,
2465                           "AFSSetFileLinkInfo Failed link of %wZ to target %wZ Status %08lX\n",
2466                           &pSrcCcb->DirectoryCB->NameInformation.FileName,
2467                           &uniTargetName,
2468                           ntStatus));
2469
2470             try_return( ntStatus);
2471         }
2472
2473         if ( ntStatus != STATUS_REPARSE)
2474         {
2475
2476             AFSInsertDirectoryNode( pTargetDcb->ObjectInformation,
2477                                     pNewTargetDirEntry,
2478                                     TRUE);
2479         }
2480
2481         //
2482         // Send notification for the target link file
2483         //
2484
2485         if( bTargetEntryExists || pNewTargetDirEntry)
2486         {
2487
2488             ulNotificationAction = FILE_ACTION_MODIFIED;
2489         }
2490         else
2491         {
2492
2493             ulNotificationAction = FILE_ACTION_ADDED;
2494         }
2495
2496         AFSFsRtlNotifyFullReportChange( pTargetParentObject,
2497                                         pSrcCcb,
2498                                         (ULONG)ulNotifyFilter,
2499                                         (ULONG)ulNotificationAction);
2500
2501       try_exit:
2502
2503         if( !NT_SUCCESS( ntStatus))
2504         {
2505
2506             if( bTargetEntryExists)
2507             {
2508
2509                 AFSInsertDirectoryNode( pTargetParentObject,
2510                                         pTargetDirEntry,
2511                                         FALSE);
2512             }
2513         }
2514
2515         if( pTargetDirEntry != NULL)
2516         {
2517
2518             //
2519             // Release DirOpenReferenceCount obtained above
2520             //
2521
2522             lCount = InterlockedDecrement( &pTargetDirEntry->DirOpenReferenceCount);
2523
2524             AFSDbgTrace(( AFS_SUBSYSTEM_DIRENTRY_REF_COUNTING,
2525                           AFS_TRACE_LEVEL_VERBOSE,
2526                           "AFSSetFileLinkInfo Decrement count on %wZ DE %p Ccb %p Cnt %d\n",
2527                           &pTargetDirEntry->NameInformation.FileName,
2528                           pTargetDirEntry,
2529                           pSrcCcb,
2530                           lCount));
2531
2532             ASSERT( lCount >= 0);
2533         }
2534
2535         if( pNewTargetDirEntry != NULL)
2536         {
2537
2538             //
2539             // Release DirOpenReferenceCount obtained from AFSNotifyHardLink
2540             //
2541
2542             lCount = InterlockedDecrement( &pNewTargetDirEntry->DirOpenReferenceCount);
2543
2544             AFSDbgTrace(( AFS_SUBSYSTEM_DIRENTRY_REF_COUNTING,
2545                           AFS_TRACE_LEVEL_VERBOSE,
2546                           "AFSSetFileLinkInfo Decrement count on %wZ DE %p Ccb %p Cnt %d\n",
2547                           &pNewTargetDirEntry->NameInformation.FileName,
2548                           pNewTargetDirEntry,
2549                           pSrcCcb,
2550                           lCount));
2551
2552             ASSERT( lCount >= 0);
2553         }
2554
2555         if( bReleaseTargetDirLock)
2556         {
2557
2558             AFSReleaseResource( pTargetParentObject->Specific.Directory.DirectoryNodeHdr.TreeLock);
2559         }
2560
2561         if ( pSrcParentObject != NULL)
2562         {
2563
2564             AFSReleaseObjectInfo( &pSrcParentObject);
2565         }
2566
2567         //
2568         // No need to release pTargetParentObject as it is either a copy of pSrcParentObject
2569         // or (AFSFcb *)pTargetFileObj->FsContext->ObjectInformation
2570         //
2571
2572         pTargetParentObject = NULL;
2573     }
2574
2575     return ntStatus;
2576 }
2577
2578 NTSTATUS
2579 AFSSetRenameInfo( IN PIRP Irp)
2580 {
2581
2582     NTSTATUS ntStatus = STATUS_SUCCESS;
2583     AFSDeviceExt *pDeviceExt = (AFSDeviceExt *)AFSRDRDeviceObject->DeviceExtension;
2584     PIO_STACK_LOCATION pIrpSp = IoGetCurrentIrpStackLocation( Irp);
2585     AFSFcb *pSrcFcb = NULL, *pTargetDcb = NULL, *pTargetFcb = NULL;
2586     AFSCcb *pSrcCcb = NULL, *pTargetDirCcb = NULL;
2587     PFILE_OBJECT pSrcFileObj = pIrpSp->FileObject;
2588     PFILE_OBJECT pTargetFileObj = pIrpSp->Parameters.SetFile.FileObject;
2589     PFILE_OBJECT pTargetParentFileObj = NULL;
2590     PFILE_RENAME_INFORMATION pRenameInfo = NULL;
2591     UNICODE_STRING uniTargetName, uniSourceName, uniTargetParentName;
2592     BOOLEAN bReplaceIfExists = FALSE;
2593     UNICODE_STRING uniShortName;
2594     AFSDirectoryCB *pTargetDirEntry = NULL;
2595     ULONG ulTargetCRC = 0;
2596     BOOLEAN bTargetEntryExists = FALSE;
2597     AFSObjectInfoCB *pSrcObject = NULL;
2598     AFSObjectInfoCB *pSrcParentObject = NULL, *pTargetParentObject = NULL;
2599     AFSFileID stNewFid;
2600     ULONG ulNotificationAction = 0, ulNotifyFilter = 0;
2601     UNICODE_STRING uniFullTargetName;
2602     BOOLEAN bCommonParent = FALSE;
2603     BOOLEAN bReleaseTargetDirLock = FALSE;
2604     BOOLEAN bReleaseSourceDirLock = FALSE;
2605     BOOLEAN bDereferenceTargetParentObject = FALSE;
2606     PERESOURCE  pSourceDirLock = NULL;
2607     LONG lCount;
2608
2609     __Enter
2610     {
2611
2612         bReplaceIfExists = pIrpSp->Parameters.SetFile.ReplaceIfExists;
2613
2614         pRenameInfo = (PFILE_RENAME_INFORMATION)Irp->AssociatedIrp.SystemBuffer;
2615
2616         pSrcFcb = (AFSFcb *)pSrcFileObj->FsContext;
2617         pSrcCcb = (AFSCcb *)pSrcFileObj->FsContext2;
2618
2619         pSrcObject = pSrcFcb->ObjectInformation;
2620
2621         if ( BooleanFlagOn( pSrcObject->Flags, AFS_OBJECT_FLAGS_PARENT_FID))
2622         {
2623
2624             pSrcParentObject = AFSFindObjectInfo( pSrcObject->VolumeCB,
2625                                                   &pSrcObject->ParentFileId,
2626                                                   TRUE);
2627         }
2628
2629         if( pSrcParentObject == NULL)
2630         {
2631
2632             AFSDbgTrace(( AFS_SUBSYSTEM_FILE_PROCESSING,
2633                           AFS_TRACE_LEVEL_ERROR,
2634                           "AFSSetRenameInfo Unable to resolve SrcParentObject (INVALID_PARAMETER)\n"));
2635
2636             ASSERT( FALSE);
2637
2638             try_return( ntStatus = STATUS_INVALID_PARAMETER);
2639         }
2640
2641         //
2642         // Perform some basic checks to ensure FS integrity
2643         //
2644
2645         if( pSrcFcb->Header.NodeTypeCode == AFS_ROOT_FCB)
2646         {
2647
2648             //
2649             // Can't rename the root directory
2650             //
2651
2652             AFSDbgTrace(( AFS_SUBSYSTEM_FILE_PROCESSING,
2653                           AFS_TRACE_LEVEL_ERROR,
2654                           "AFSSetRenameInfo Attempt to rename root entry\n"));
2655
2656             try_return( ntStatus = STATUS_INVALID_PARAMETER);
2657         }
2658
2659         if( pSrcFcb->Header.NodeTypeCode == AFS_DIRECTORY_FCB)
2660         {
2661
2662             //
2663             // If there are any open children then fail the rename
2664             //
2665
2666             if( pSrcObject->Specific.Directory.ChildOpenHandleCount > 0)
2667             {
2668
2669                 AFSDbgTrace(( AFS_SUBSYSTEM_FILE_PROCESSING,
2670                               AFS_TRACE_LEVEL_ERROR,
2671                               "AFSSetRenameInfo Attempt to rename directory with open children %wZ\n",
2672                               &pSrcCcb->DirectoryCB->NameInformation.FileName));
2673
2674                 try_return( ntStatus = STATUS_ACCESS_DENIED);
2675             }
2676         }
2677
2678
2679         //
2680         // Extract off the final component name from the Fcb
2681         //
2682
2683         uniSourceName.Length = (USHORT)pSrcCcb->DirectoryCB->NameInformation.FileName.Length;
2684         uniSourceName.MaximumLength = uniSourceName.Length;
2685
2686         uniSourceName.Buffer = pSrcCcb->DirectoryCB->NameInformation.FileName.Buffer;
2687
2688         //
2689         // Resolve the target fileobject
2690         //
2691
2692         if( pTargetFileObj == NULL)
2693         {
2694
2695             if ( pRenameInfo->RootDirectory)
2696             {
2697
2698                 AFSDbgTrace(( AFS_SUBSYSTEM_FILE_PROCESSING,
2699                               AFS_TRACE_LEVEL_ERROR,
2700                               "AFSSetRenameInfo Handle provided but no FileObject ntStatus INVALID_PARAMETER\n"));
2701
2702                 try_return( ntStatus = STATUS_INVALID_PARAMETER);
2703             }
2704             else
2705             {
2706
2707                 uniFullTargetName.Length = (USHORT)pRenameInfo->FileNameLength;
2708
2709                 uniFullTargetName.Buffer = (PWSTR)&pRenameInfo->FileName;
2710
2711                 AFSRetrieveFinalComponent( &uniFullTargetName,
2712                                            &uniTargetName);
2713
2714                 AFSRetrieveParentPath( &uniFullTargetName,
2715                                        &uniTargetParentName);
2716
2717                 if ( uniTargetParentName.Length == 0)
2718                 {
2719
2720                     //
2721                     // This is a simple rename. Here the target directory is the same as the source parent directory
2722                     // and the name is retrieved from the system buffer information
2723                     //
2724
2725                     pTargetParentObject = pSrcParentObject;
2726                 }
2727                 else
2728                 {
2729                     //
2730                     // uniTargetParentName contains the directory the renamed object
2731                     // will be moved to.  Must obtain the TargetParentObject.
2732                     //
2733
2734                     AFSDbgTrace(( AFS_SUBSYSTEM_FILE_PROCESSING,
2735                                   AFS_TRACE_LEVEL_ERROR,
2736                                   "AFSSetRenameInfo Attempt to move %wZ to %wZ -- not yet supported (NOT_SAME_DEVICE)\n",
2737                                   &pSrcCcb->DirectoryCB->NameInformation.FileName,
2738                                   &uniFullTargetName));
2739
2740                     try_return( ntStatus = STATUS_NOT_SAME_DEVICE);
2741                 }
2742             }
2743
2744             pTargetDcb = pTargetParentObject->Fcb;
2745         }
2746         else
2747         {
2748
2749             //
2750             // So here we have the target directory taken from the targetfile object
2751             //
2752
2753             pTargetDcb = (AFSFcb *)pTargetFileObj->FsContext;
2754
2755             pTargetDirCcb = (AFSCcb *)pTargetFileObj->FsContext2;
2756
2757             pTargetParentObject = (AFSObjectInfoCB *)pTargetDcb->ObjectInformation;
2758
2759             //
2760             // Grab the target name which we setup in the IRP_MJ_CREATE handler. By how we set this up
2761             // it is only the target component of the rename operation
2762             //
2763
2764             uniTargetName = *((PUNICODE_STRING)&pTargetFileObj->FileName);
2765         }
2766
2767         //
2768         // The quick check to see if they are not really performing a rename
2769         // Do the names match? Only do this where the parent directories are
2770         // the same
2771         //
2772
2773         if( pTargetParentObject == pSrcParentObject)
2774         {
2775
2776             if( FsRtlAreNamesEqual( &uniTargetName,
2777                                     &uniSourceName,
2778                                     FALSE,
2779                                     NULL))
2780             {
2781                 try_return( ntStatus = STATUS_SUCCESS);
2782             }
2783
2784             bCommonParent = TRUE;
2785         }
2786         else
2787         {
2788
2789             bCommonParent = FALSE;
2790         }
2791
2792         //
2793         // We do not allow cross-volume renames to occur
2794         //
2795
2796         if( pTargetParentObject->VolumeCB != pSrcObject->VolumeCB)
2797         {
2798
2799             AFSDbgTrace(( AFS_SUBSYSTEM_FILE_PROCESSING,
2800                           AFS_TRACE_LEVEL_ERROR,
2801                           "AFSSetRenameInfo Attempt to rename directory to different volume %wZ\n",
2802                           &pSrcCcb->DirectoryCB->NameInformation.FileName));
2803
2804             try_return( ntStatus = STATUS_NOT_SAME_DEVICE);
2805         }
2806
2807         ulTargetCRC = AFSGenerateCRC( &uniTargetName,
2808                                       FALSE);
2809
2810         AFSAcquireExcl( pTargetParentObject->Specific.Directory.DirectoryNodeHdr.TreeLock,
2811                         TRUE);
2812
2813         bReleaseTargetDirLock = TRUE;
2814
2815         if( pTargetParentObject != pSrcParentObject)
2816         {
2817             AFSAcquireExcl( pSrcParentObject->Specific.Directory.DirectoryNodeHdr.TreeLock,
2818                             TRUE);
2819
2820             bReleaseSourceDirLock = TRUE;
2821
2822             pSourceDirLock = pSrcParentObject->Specific.Directory.DirectoryNodeHdr.TreeLock;
2823         }
2824
2825         AFSLocateCaseSensitiveDirEntry( pTargetParentObject->Specific.Directory.DirectoryNodeHdr.CaseSensitiveTreeHead,
2826                                         ulTargetCRC,
2827                                         &pTargetDirEntry);
2828
2829         if( pTargetDirEntry == NULL)
2830         {
2831
2832             //
2833             // Missed so perform a case insensitive lookup
2834             //
2835
2836             ulTargetCRC = AFSGenerateCRC( &uniTargetName,
2837                                           TRUE);
2838
2839             AFSLocateCaseInsensitiveDirEntry( pTargetParentObject->Specific.Directory.DirectoryNodeHdr.CaseInsensitiveTreeHead,
2840                                               ulTargetCRC,
2841                                               &pTargetDirEntry);
2842         }
2843
2844         if ( !BooleanFlagOn( pDeviceExt->DeviceFlags, AFS_DEVICE_FLAG_DISABLE_SHORTNAMES) &&
2845              pTargetDirEntry == NULL && RtlIsNameLegalDOS8Dot3( &uniTargetName,
2846                                                                NULL,
2847                                                                NULL))
2848         {
2849             //
2850             // Try the short name
2851             //
2852             AFSLocateShortNameDirEntry( pTargetParentObject->Specific.Directory.ShortNameTree,
2853                                         ulTargetCRC,
2854                                         &pTargetDirEntry);
2855         }
2856
2857         //
2858         // Increment our ref count on the dir entry
2859         //
2860
2861         if( pTargetDirEntry != NULL)
2862         {
2863
2864             ASSERT( BooleanFlagOn( pTargetDirEntry->ObjectInformation->Flags, AFS_OBJECT_FLAGS_PARENT_FID) &&
2865                     AFSIsEqualFID( &pTargetParentObject->FileId, &pTargetDirEntry->ObjectInformation->ParentFileId));
2866
2867             lCount = InterlockedIncrement( &pTargetDirEntry->DirOpenReferenceCount);
2868
2869             AFSDbgTrace(( AFS_SUBSYSTEM_DIRENTRY_REF_COUNTING,
2870                           AFS_TRACE_LEVEL_VERBOSE,
2871                           "AFSSetRenameInfo Increment count on %wZ DE %p Ccb %p Cnt %d\n",
2872                           &pTargetDirEntry->NameInformation.FileName,
2873                           pTargetDirEntry,
2874                           pSrcCcb,
2875                           lCount));
2876
2877             ASSERT( lCount >= 0);
2878
2879             //
2880             // Need to acquire the ObjectInfoLock while checking for the Fcb OpenRefCount so we don't race with
2881             // a tear down worker thread on the Fcb
2882             //
2883
2884             AFSAcquireShared( &pTargetDirEntry->ObjectInformation->NonPagedInfo->ObjectInfoLock,
2885                               TRUE);
2886
2887             //
2888             // Check there are no current opens on the target
2889             //
2890
2891             if( BooleanFlagOn( pTargetDirEntry->ObjectInformation->FileAttributes, FILE_ATTRIBUTE_READONLY) ||
2892                 ( pTargetDirEntry->ObjectInformation->Fcb != NULL &&
2893                   pTargetDirEntry->ObjectInformation->Fcb->OpenReferenceCount != 0))
2894             {
2895
2896                 //
2897                 // Return the correct error code
2898                 //
2899
2900                 if( BooleanFlagOn( pTargetDirEntry->Flags, AFS_DIR_ENTRY_PENDING_DELETE))
2901                 {
2902                     ntStatus = STATUS_DELETE_PENDING;
2903                 }
2904                 else
2905                 {
2906                     ntStatus = STATUS_ACCESS_DENIED;
2907                 }
2908
2909                 AFSReleaseResource( &pTargetDirEntry->ObjectInformation->NonPagedInfo->ObjectInfoLock);
2910
2911                 AFSDbgTrace(( AFS_SUBSYSTEM_FILE_PROCESSING,
2912                               AFS_TRACE_LEVEL_ERROR,
2913                               "AFSSetRenameInfo Attempt to rename %s Target %wZ Status %08lX\n",
2914                               BooleanFlagOn( pTargetDirEntry->ObjectInformation->FileAttributes, FILE_ATTRIBUTE_READONLY)?"ReadOnly":"Open",
2915                               &pTargetDirEntry->NameInformation.FileName,
2916                               ntStatus));
2917
2918                 try_return( ntStatus);
2919             }
2920
2921             AFSReleaseResource( &pTargetDirEntry->ObjectInformation->NonPagedInfo->ObjectInfoLock);
2922
2923             if( !bReplaceIfExists)
2924             {
2925
2926                 AFSDbgTrace(( AFS_SUBSYSTEM_FILE_PROCESSING,
2927                               AFS_TRACE_LEVEL_ERROR,
2928                               "AFSSetRenameInfo Attempt to rename directory with target collision %wZ Target %wZ\n",
2929                               &pSrcCcb->DirectoryCB->NameInformation.FileName,
2930                               &pTargetDirEntry->NameInformation.FileName));
2931
2932                 try_return( ntStatus = STATUS_OBJECT_NAME_COLLISION);
2933             }
2934
2935             AFSDbgTrace(( AFS_SUBSYSTEM_FILE_PROCESSING | AFS_SUBSYSTEM_DIRENTRY_REF_COUNTING,
2936                           AFS_TRACE_LEVEL_ERROR,
2937                           "AFSSetRenameInfo Target %wZ exists DE %p Count %d, performing delete of target\n",
2938                           &pTargetDirEntry->NameInformation.FileName,
2939                           pTargetDirEntry,
2940                           lCount));
2941
2942             //
2943             // Pull the directory entry from the parent
2944             //
2945
2946             AFSRemoveDirNodeFromParent( pTargetParentObject,
2947                                         pTargetDirEntry,
2948                                         FALSE);
2949
2950             bTargetEntryExists = TRUE;
2951         }
2952         else
2953         {
2954             AFSDbgTrace(( AFS_SUBSYSTEM_FILE_PROCESSING,
2955                           AFS_TRACE_LEVEL_VERBOSE,
2956                           "AFSSetRenameInfo Target does NOT exist, normal rename\n"));
2957         }
2958
2959         //
2960         // We need to remove the DirEntry from the parent node, update the index
2961         // and reinsert it into the parent tree. Note that for entries with the
2962         // same parent we do not pull the node from the enumeration list
2963         //
2964
2965         AFSRemoveDirNodeFromParent( pSrcParentObject,
2966                                     pSrcCcb->DirectoryCB,
2967                                     !bCommonParent);
2968
2969         //
2970         // OK, this is a simple rename. Issue the rename
2971         // request to the service.
2972         //
2973
2974         ntStatus = AFSNotifyRename( pSrcObject,
2975                                     &pSrcCcb->AuthGroup,
2976                                     pSrcParentObject,
2977                                     pTargetDcb->ObjectInformation,
2978                                     pSrcCcb->DirectoryCB,
2979                                     &uniTargetName,
2980                                     &stNewFid);
2981
2982         if( !NT_SUCCESS( ntStatus))
2983         {
2984
2985             //
2986             // Attempt to re-insert the directory entry
2987             //
2988
2989             AFSInsertDirectoryNode( pSrcParentObject,
2990                                     pSrcCcb->DirectoryCB,
2991                                     !bCommonParent);
2992
2993             AFSDbgTrace(( AFS_SUBSYSTEM_FILE_PROCESSING,
2994                           AFS_TRACE_LEVEL_ERROR,
2995                           "AFSSetRenameInfo Failed rename of %wZ to target %wZ Status %08lX\n",
2996                           &pSrcCcb->DirectoryCB->NameInformation.FileName,
2997                           &uniTargetName,
2998                           ntStatus));
2999
3000             try_return( ntStatus);
3001         }
3002
3003         //
3004         // Set the notification up for the source file
3005         //
3006
3007         if( pSrcParentObject == pTargetParentObject &&
3008             !bTargetEntryExists)
3009         {
3010
3011             ulNotificationAction = FILE_ACTION_RENAMED_OLD_NAME;
3012         }
3013         else
3014         {
3015
3016             ulNotificationAction = FILE_ACTION_REMOVED;
3017         }
3018
3019         if( pSrcObject->FileType == AFS_FILE_TYPE_DIRECTORY)
3020         {
3021
3022             ulNotifyFilter = FILE_NOTIFY_CHANGE_DIR_NAME;
3023         }
3024         else
3025         {
3026
3027             ulNotifyFilter = FILE_NOTIFY_CHANGE_FILE_NAME;
3028         }
3029
3030         AFSFsRtlNotifyFullReportChange( pSrcParentObject,
3031                                         pSrcCcb,
3032                                         (ULONG)ulNotifyFilter,
3033                                         (ULONG)ulNotificationAction);
3034
3035         //
3036         // Update the name in the dir entry.
3037         //
3038
3039         ntStatus = AFSUpdateDirEntryName( pSrcCcb->DirectoryCB,
3040                                           &uniTargetName);
3041
3042         if( !NT_SUCCESS( ntStatus))
3043         {
3044
3045             //
3046             // Attempt to re-insert the directory entry
3047             //
3048
3049             AFSInsertDirectoryNode( pSrcParentObject,
3050                                     pSrcCcb->DirectoryCB,
3051                                     !bCommonParent);
3052
3053             AFSDbgTrace(( AFS_SUBSYSTEM_FILE_PROCESSING,
3054                           AFS_TRACE_LEVEL_ERROR,
3055                           "AFSSetRenameInfo Failed update of dir entry %wZ to target %wZ Status %08lX\n",
3056                           &pSrcCcb->DirectoryCB->NameInformation.FileName,
3057                           &uniTargetName,
3058                           ntStatus));
3059
3060             try_return( ntStatus);
3061         }
3062
3063         //
3064         // Update the object information block, if needed
3065         //
3066
3067         if( !AFSIsEqualFID( &pSrcObject->FileId,
3068                             &stNewFid))
3069         {
3070
3071             AFSAcquireExcl( pSrcObject->VolumeCB->ObjectInfoTree.TreeLock,
3072                             TRUE);
3073
3074             //
3075             // Remove the old information entry
3076             //
3077
3078             AFSRemoveHashEntry( &pSrcObject->VolumeCB->ObjectInfoTree.TreeHead,
3079                                 &pSrcObject->TreeEntry);
3080
3081             RtlCopyMemory( &pSrcObject->FileId,
3082                            &stNewFid,
3083                            sizeof( AFSFileID));
3084
3085             //
3086             // Insert the entry into the new object table.
3087             //
3088
3089             pSrcObject->TreeEntry.HashIndex = AFSCreateLowIndex( &pSrcObject->FileId);
3090
3091             if( pSrcObject->VolumeCB->ObjectInfoTree.TreeHead == NULL)
3092             {
3093
3094                 pSrcObject->VolumeCB->ObjectInfoTree.TreeHead = &pSrcObject->TreeEntry;
3095             }
3096             else
3097             {
3098
3099                 if ( !NT_SUCCESS( AFSInsertHashEntry( pSrcObject->VolumeCB->ObjectInfoTree.TreeHead,
3100                                                      &pSrcObject->TreeEntry)))
3101                 {
3102
3103                     //
3104                     // Lost a race, an ObjectInfo object already exists for this FID.
3105                     // Let this copy be garbage collected.
3106                     //
3107
3108                     ClearFlag( pSrcObject->Flags, AFS_OBJECT_INSERTED_HASH_TREE);
3109                 }
3110             }
3111
3112             AFSReleaseResource( pSrcObject->VolumeCB->ObjectInfoTree.TreeLock);
3113         }
3114
3115         //
3116         // Update the hash values for the name trees.
3117         //
3118
3119         pSrcCcb->DirectoryCB->CaseSensitiveTreeEntry.HashIndex = AFSGenerateCRC( &pSrcCcb->DirectoryCB->NameInformation.FileName,
3120                                                                                  FALSE);
3121
3122         pSrcCcb->DirectoryCB->CaseInsensitiveTreeEntry.HashIndex = AFSGenerateCRC( &pSrcCcb->DirectoryCB->NameInformation.FileName,
3123                                                                                    TRUE);
3124
3125         if( !BooleanFlagOn( pDeviceExt->DeviceFlags, AFS_DEVICE_FLAG_DISABLE_SHORTNAMES) &&
3126             pSrcCcb->DirectoryCB->NameInformation.ShortNameLength > 0 &&
3127             !RtlIsNameLegalDOS8Dot3( &pSrcCcb->DirectoryCB->NameInformation.FileName,
3128                                      NULL,
3129                                      NULL))
3130         {
3131
3132             uniShortName.Length = pSrcCcb->DirectoryCB->NameInformation.ShortNameLength;
3133             uniShortName.MaximumLength = uniShortName.Length;
3134             uniShortName.Buffer = pSrcCcb->DirectoryCB->NameInformation.ShortName;
3135
3136             pSrcCcb->DirectoryCB->Type.Data.ShortNameTreeEntry.HashIndex = AFSGenerateCRC( &uniShortName,
3137                                                                                            TRUE);
3138
3139             AFSDbgTrace(( AFS_SUBSYSTEM_FILE_PROCESSING,
3140                           AFS_TRACE_LEVEL_VERBOSE,
3141                           "AFSSetRenameInfo Initialized short name hash for %wZ longname %wZ\n",
3142                           &uniShortName,
3143                           &pSrcCcb->DirectoryCB->NameInformation.FileName));
3144         }
3145         else
3146         {
3147
3148             pSrcCcb->DirectoryCB->Type.Data.ShortNameTreeEntry.HashIndex = 0;
3149         }
3150
3151         if( !bCommonParent)
3152         {
3153
3154             //
3155             // Update the file index for the object in the new parent
3156             //
3157
3158             pSrcCcb->DirectoryCB->FileIndex = (ULONG)InterlockedIncrement( &pTargetParentObject->Specific.Directory.DirectoryNodeHdr.ContentIndex);
3159         }
3160
3161         //
3162         // Re-insert the directory entry
3163         //
3164
3165         AFSInsertDirectoryNode( pTargetParentObject,
3166                                 pSrcCcb->DirectoryCB,
3167                                 !bCommonParent);
3168
3169         //
3170         // Update the parent pointer in the source object if they are different
3171         //
3172
3173         if( pSrcParentObject != pTargetParentObject)
3174         {
3175
3176             lCount = InterlockedDecrement( &pSrcParentObject->Specific.Directory.ChildOpenHandleCount);
3177
3178   &