2 * Copyright (c) 2008, 2009, 2010, 2011 Kernel Drivers, LLC.
3 * Copyright (c) 2009, 2010, 2011 Your File System, Inc.
6 * Redistribution and use in source and binary forms, with or without
7 * modification, are permitted provided that the following conditions
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
14 * this list of conditions and the following disclaimer in the
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.
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.
36 // File: AFSFileInfo.cpp
39 #include "AFSCommon.h"
42 // Function: AFSQueryFileInfo
46 // This function is the dispatch handler for the IRP_MJ_QUERY_FILE_INFORMATION request
50 // A status is returned for the function
54 AFSQueryFileInfo( IN PDEVICE_OBJECT LibDeviceObject,
58 NTSTATUS ntStatus = STATUS_SUCCESS;
59 AFSDeviceExt *pDeviceExt = (AFSDeviceExt *)AFSRDRDeviceObject->DeviceExtension;
60 ULONG ulRequestType = 0;
61 IO_STACK_LOCATION *pIrpSp = IoGetCurrentIrpStackLocation( Irp);
64 PFILE_OBJECT pFileObject;
65 BOOLEAN bReleaseMain = FALSE;
67 FILE_INFORMATION_CLASS stFileInformationClass;
75 // Determine the type of request this request is
78 pFcb = (AFSFcb *)pIrpSp->FileObject->FsContext;
80 pCcb = (AFSCcb *)pIrpSp->FileObject->FsContext2;
85 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
86 AFS_TRACE_LEVEL_ERROR,
87 "AFSQueryFileInfo Attempted access (%08lX) when pFcb == NULL\n",
90 try_return( ntStatus = STATUS_INVALID_DEVICE_REQUEST);
93 lLength = (LONG)pIrpSp->Parameters.QueryFile.Length;
94 stFileInformationClass = pIrpSp->Parameters.QueryFile.FileInformationClass;
95 pBuffer = Irp->AssociatedIrp.SystemBuffer;
97 RtlZeroMemory( &stAuthGroup,
100 AFSRetrieveAuthGroupFnc( (ULONGLONG)PsGetCurrentProcessId(),
101 (ULONGLONG)PsGetCurrentThreadId(),
104 AFSVerifyEntry( &stAuthGroup,
108 // Grab the main shared right off the bat
111 AFSDbgLogMsg( AFS_SUBSYSTEM_LOCK_PROCESSING,
112 AFS_TRACE_LEVEL_VERBOSE,
113 "AFSQueryFileInfo Acquiring Fcb lock %08lX SHARED %08lX\n",
114 &pFcb->NPFcb->Resource,
115 PsGetCurrentThread());
117 AFSAcquireShared( &pFcb->NPFcb->Resource,
123 // Don't allow requests against IOCtl nodes
126 if( pFcb->Header.NodeTypeCode == AFS_SPECIAL_SHARE_FCB)
129 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
130 AFS_TRACE_LEVEL_VERBOSE,
131 "AFSQueryFileInfo Processing request against SpecialShare Fcb\n");
133 ntStatus = AFSProcessShareQueryInfo( Irp,
137 try_return( ntStatus);
139 else if( pFcb->Header.NodeTypeCode == AFS_IOCTL_FCB)
141 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
142 AFS_TRACE_LEVEL_VERBOSE,
143 "AFSQueryFileInfo request against PIOCtl Fcb\n");
145 ntStatus = AFSProcessPIOCtlQueryInfo( Irp,
150 try_return( ntStatus);
153 else if( pFcb->Header.NodeTypeCode == AFS_INVALID_FCB)
155 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
156 AFS_TRACE_LEVEL_VERBOSE,
157 "AFSQueryFileInfo request against Invalid Fcb\n");
159 try_return( ntStatus = STATUS_ACCESS_DENIED);
163 // Process the request
166 switch( stFileInformationClass)
169 case FileAllInformation:
172 PFILE_ALL_INFORMATION pAllInfo;
175 // For the all information class we'll typecast a local
176 // pointer to the output buffer and then call the
177 // individual routines to fill in the buffer.
180 pAllInfo = (PFILE_ALL_INFORMATION)pBuffer;
182 ntStatus = AFSQueryBasicInfo( Irp,
184 &pAllInfo->BasicInformation,
187 if( !NT_SUCCESS( ntStatus))
190 try_return( ntStatus);
193 ntStatus = AFSQueryStandardInfo( Irp,
195 &pAllInfo->StandardInformation,
198 if( !NT_SUCCESS( ntStatus))
201 try_return( ntStatus);
204 ntStatus = AFSQueryInternalInfo( Irp,
206 &pAllInfo->InternalInformation,
209 if( !NT_SUCCESS( ntStatus))
212 try_return( ntStatus);
215 ntStatus = AFSQueryEaInfo( Irp,
217 &pAllInfo->EaInformation,
220 if( !NT_SUCCESS( ntStatus))
223 try_return( ntStatus);
226 ntStatus = AFSQueryAccess( Irp,
228 &pAllInfo->AccessInformation,
231 if( !NT_SUCCESS( ntStatus))
234 try_return( ntStatus);
237 ntStatus = AFSQueryPositionInfo( Irp,
239 &pAllInfo->PositionInformation,
242 if( !NT_SUCCESS( ntStatus))
245 try_return( ntStatus);
248 ntStatus = AFSQueryMode( Irp,
250 &pAllInfo->ModeInformation,
253 if( !NT_SUCCESS( ntStatus))
256 try_return( ntStatus);
259 ntStatus = AFSQueryAlignment( Irp,
261 &pAllInfo->AlignmentInformation,
264 if( !NT_SUCCESS( ntStatus))
267 try_return( ntStatus);
270 ntStatus = AFSQueryNameInfo( Irp,
272 &pAllInfo->NameInformation,
275 if( !NT_SUCCESS( ntStatus))
278 try_return( ntStatus);
284 case FileBasicInformation:
287 ntStatus = AFSQueryBasicInfo( Irp,
289 (PFILE_BASIC_INFORMATION)pBuffer,
295 case FileStandardInformation:
298 ntStatus = AFSQueryStandardInfo( Irp,
300 (PFILE_STANDARD_INFORMATION)pBuffer,
306 case FileInternalInformation:
309 ntStatus = AFSQueryInternalInfo( Irp,
311 (PFILE_INTERNAL_INFORMATION)pBuffer,
317 case FileEaInformation:
320 ntStatus = AFSQueryEaInfo( Irp,
322 (PFILE_EA_INFORMATION)pBuffer,
328 case FilePositionInformation:
331 ntStatus = AFSQueryPositionInfo( Irp,
333 (PFILE_POSITION_INFORMATION)pBuffer,
339 case FileNormalizedNameInformation:
340 case FileNameInformation:
343 ntStatus = AFSQueryNameInfo( Irp,
345 (PFILE_NAME_INFORMATION)pBuffer,
351 case FileAlternateNameInformation:
354 ntStatus = AFSQueryShortNameInfo( Irp,
356 (PFILE_NAME_INFORMATION)pBuffer,
362 case FileNetworkOpenInformation:
365 ntStatus = AFSQueryNetworkInfo( Irp,
367 (PFILE_NETWORK_OPEN_INFORMATION)pBuffer,
373 case FileStreamInformation:
376 ntStatus = AFSQueryStreamInfo( Irp,
378 (FILE_STREAM_INFORMATION *)pBuffer,
385 case FileAttributeTagInformation:
388 ntStatus = AFSQueryAttribTagInfo( Irp,
390 (FILE_ATTRIBUTE_TAG_INFORMATION *)pBuffer,
396 case FileRemoteProtocolInformation:
399 ntStatus = AFSQueryRemoteProtocolInfo( Irp,
401 (FILE_REMOTE_PROTOCOL_INFORMATION *)pBuffer,
407 case FileNetworkPhysicalNameInformation:
410 ntStatus = AFSQueryPhysicalNameInfo( Irp,
412 (FILE_NETWORK_PHYSICAL_NAME_INFORMATION *)pBuffer,
420 ntStatus = STATUS_INVALID_PARAMETER;
427 Irp->IoStatus.Information = pIrpSp->Parameters.QueryFile.Length - lLength;
432 AFSReleaseResource( &pFcb->NPFcb->Resource);
435 if( !NT_SUCCESS( ntStatus) &&
436 ntStatus != STATUS_INVALID_PARAMETER &&
437 ntStatus != STATUS_BUFFER_OVERFLOW)
441 pCcb->DirectoryCB != NULL)
444 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
445 AFS_TRACE_LEVEL_ERROR,
446 "AFSQueryFileInfo Failed to process request for %wZ FID %08lX-%08lX-%08lX-%08lX Status %08lX\n",
447 &pCcb->DirectoryCB->NameInformation.FileName,
448 pCcb->DirectoryCB->ObjectInformation->FileId.Cell,
449 pCcb->DirectoryCB->ObjectInformation->FileId.Volume,
450 pCcb->DirectoryCB->ObjectInformation->FileId.Vnode,
451 pCcb->DirectoryCB->ObjectInformation->FileId.Unique,
456 __except( AFSExceptionFilter( __FUNCTION__, GetExceptionCode(), GetExceptionInformation()) )
461 "EXCEPTION - AFSQueryFileInfo\n");
463 AFSDumpTraceFilesFnc();
465 ntStatus = STATUS_UNSUCCESSFUL;
470 AFSReleaseResource( &pFcb->NPFcb->Resource);
474 AFSCompleteRequest( Irp,
481 // Function: AFSSetFileInfo
485 // This function is the dispatch handler for the IRP_MJ_SET_FILE_INFORMATION request
489 // A status is returned for the function
493 AFSSetFileInfo( IN PDEVICE_OBJECT LibDeviceObject,
497 NTSTATUS ntStatus = STATUS_SUCCESS;
498 AFSDeviceExt *pDeviceExt = (AFSDeviceExt *)AFSRDRDeviceObject->DeviceExtension;
499 IO_STACK_LOCATION *pIrpSp = IoGetCurrentIrpStackLocation( Irp);
502 BOOLEAN bCompleteRequest = TRUE;
503 FILE_INFORMATION_CLASS FileInformationClass;
504 BOOLEAN bCanQueueRequest = FALSE;
505 PFILE_OBJECT pFileObject = NULL;
506 BOOLEAN bReleaseMain = FALSE;
507 BOOLEAN bUpdateFileInfo = FALSE;
508 AFSFileID stParentFileId;
513 pFileObject = pIrpSp->FileObject;
515 pFcb = (AFSFcb *)pFileObject->FsContext;
516 pCcb = (AFSCcb *)pFileObject->FsContext2;
521 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
522 AFS_TRACE_LEVEL_ERROR,
523 "AFSSetFileInfo Attempted access (%08lX) when pFcb == NULL\n",
526 try_return( ntStatus = STATUS_INVALID_DEVICE_REQUEST);
529 bCanQueueRequest = !(IoIsOperationSynchronous( Irp) | (KeGetCurrentIrql() != PASSIVE_LEVEL));
530 FileInformationClass = pIrpSp->Parameters.SetFile.FileInformationClass;
536 AFSDbgLogMsg( AFS_SUBSYSTEM_LOCK_PROCESSING,
537 AFS_TRACE_LEVEL_VERBOSE,
538 "AFSSetFileInfo Acquiring Fcb lock %08lX EXCL %08lX\n",
539 &pFcb->NPFcb->Resource,
540 PsGetCurrentThread());
542 AFSAcquireExcl( &pFcb->NPFcb->Resource,
548 // Don't allow requests against IOCtl nodes
551 if( pFcb->Header.NodeTypeCode == AFS_IOCTL_FCB)
554 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
555 AFS_TRACE_LEVEL_ERROR,
556 "AFSSetFileInfo Failing request against PIOCtl Fcb\n");
558 try_return( ntStatus = STATUS_INVALID_DEVICE_REQUEST);
560 else if( pFcb->Header.NodeTypeCode == AFS_SPECIAL_SHARE_FCB)
563 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
564 AFS_TRACE_LEVEL_VERBOSE,
565 "AFSSetFileInfo Processing request against SpecialShare Fcb\n");
567 ntStatus = AFSProcessShareSetInfo( Irp,
571 try_return( ntStatus);
574 if( BooleanFlagOn( pFcb->ObjectInformation->VolumeCB->VolumeInformation.Characteristics, FILE_READ_ONLY_DEVICE))
577 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
578 AFS_TRACE_LEVEL_ERROR,
579 "AFSSetFileInfo Request failed due to read only volume\n",
582 try_return( ntStatus = STATUS_MEDIA_WRITE_PROTECTED);
585 if( pFcb->Header.NodeTypeCode == AFS_INVALID_FCB &&
586 FileInformationClass != FileDispositionInformation)
588 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
589 AFS_TRACE_LEVEL_VERBOSE,
590 "AFSSetFileInfo request against Invalid Fcb\n");
592 try_return( ntStatus = STATUS_ACCESS_DENIED);
596 // Ensure rename operations are synchronous
599 if( FileInformationClass == FileRenameInformation)
602 bCanQueueRequest = FALSE;
606 // Store away the parent fid
609 RtlZeroMemory( &stParentFileId,
612 if( pFcb->ObjectInformation->ParentObjectInformation != NULL)
614 stParentFileId = pFcb->ObjectInformation->ParentObjectInformation->FileId;
618 // Process the request
621 switch( FileInformationClass)
624 case FileBasicInformation:
627 bUpdateFileInfo = TRUE;
629 ntStatus = AFSSetBasicInfo( Irp,
635 case FileDispositionInformation:
638 ntStatus = AFSSetDispositionInfo( Irp,
644 case FileRenameInformation:
647 ntStatus = AFSSetRenameInfo( Irp);
652 case FilePositionInformation:
655 ntStatus = AFSSetPositionInfo( Irp,
661 case FileLinkInformation:
664 ntStatus = AFSSetFileLinkInfo( Irp);
669 case FileAllocationInformation:
672 ntStatus = AFSSetAllocationInfo( Irp,
678 case FileEndOfFileInformation:
681 ntStatus = AFSSetEndOfFileInfo( Irp,
689 ntStatus = STATUS_INVALID_PARAMETER;
699 AFSReleaseResource( &pFcb->NPFcb->Resource);
702 if( NT_SUCCESS( ntStatus) &&
706 ntStatus = AFSUpdateFileInformation( &stParentFileId,
707 pFcb->ObjectInformation,
710 if( !NT_SUCCESS( ntStatus))
713 AFSAcquireExcl( &pFcb->NPFcb->Resource,
717 // Unwind the update and fail the request
720 AFSUnwindFileInfo( pFcb,
723 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
724 AFS_TRACE_LEVEL_ERROR,
725 "AFSSetFileInfo Failed to send file info update to service request for %wZ FID %08lX-%08lX-%08lX-%08lX Status %08lX\n",
726 &pCcb->DirectoryCB->NameInformation.FileName,
727 pCcb->DirectoryCB->ObjectInformation->FileId.Cell,
728 pCcb->DirectoryCB->ObjectInformation->FileId.Volume,
729 pCcb->DirectoryCB->ObjectInformation->FileId.Vnode,
730 pCcb->DirectoryCB->ObjectInformation->FileId.Unique,
733 AFSReleaseResource( &pFcb->NPFcb->Resource);
737 if( !NT_SUCCESS( ntStatus))
741 pCcb->DirectoryCB != NULL)
744 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
745 AFS_TRACE_LEVEL_ERROR,
746 "AFSSetFileInfo Failed to process request for %wZ FID %08lX-%08lX-%08lX-%08lX Status %08lX\n",
747 &pCcb->DirectoryCB->NameInformation.FileName,
748 pCcb->DirectoryCB->ObjectInformation->FileId.Cell,
749 pCcb->DirectoryCB->ObjectInformation->FileId.Volume,
750 pCcb->DirectoryCB->ObjectInformation->FileId.Vnode,
751 pCcb->DirectoryCB->ObjectInformation->FileId.Unique,
756 __except( AFSExceptionFilter( __FUNCTION__, GetExceptionCode(), GetExceptionInformation()) )
761 "EXCEPTION - AFSSetFileInfo\n");
763 AFSDumpTraceFilesFnc();
765 ntStatus = STATUS_UNSUCCESSFUL;
770 AFSReleaseResource( &pFcb->NPFcb->Resource);
774 AFSCompleteRequest( Irp,
781 // Function: AFSQueryBasicInfo
785 // This function is the handler for the query basic information request
789 // A status is returned for the function
793 AFSQueryBasicInfo( IN PIRP Irp,
794 IN AFSDirectoryCB *DirectoryCB,
795 IN OUT PFILE_BASIC_INFORMATION Buffer,
798 NTSTATUS ntStatus = STATUS_SUCCESS;
799 AFSDeviceExt *pDeviceExt = (AFSDeviceExt *)AFSRDRDeviceObject->DeviceExtension;
800 ULONG ulFileAttribs = 0;
803 IO_STACK_LOCATION *pIrpSp = IoGetCurrentIrpStackLocation( Irp);
804 AFSFileInfoCB stFileInfo;
805 AFSDirectoryCB *pParentDirectoryCB = NULL;
806 UNICODE_STRING uniParentPath;
808 if( *Length >= sizeof( FILE_BASIC_INFORMATION))
811 RtlZeroMemory( Buffer,
814 ulFileAttribs = DirectoryCB->ObjectInformation->FileAttributes;
816 pFcb = (AFSFcb *)pIrpSp->FileObject->FsContext;
817 pCcb = (AFSCcb *)pIrpSp->FileObject->FsContext2;
819 if( DirectoryCB->ObjectInformation->FileType == AFS_FILE_TYPE_SYMLINK)
822 pParentDirectoryCB = AFSGetParentEntry( pCcb->NameArray);
824 AFSRetrieveParentPath( &pCcb->FullFileName,
827 RtlZeroMemory( &stFileInfo,
828 sizeof( AFSFileInfoCB));
831 // Can't hold the Fcb while evaluating the path, leads to lock inversion
834 AFSReleaseResource( &pFcb->NPFcb->Resource);
836 if( NT_SUCCESS( AFSRetrieveFileAttributes( pParentDirectoryCB,
844 if ( ulFileAttribs == FILE_ATTRIBUTE_NORMAL)
847 ulFileAttribs = FILE_ATTRIBUTE_REPARSE_POINT;
852 ulFileAttribs |= FILE_ATTRIBUTE_REPARSE_POINT;
855 if ( stFileInfo.FileAttributes & FILE_ATTRIBUTE_DIRECTORY)
858 ulFileAttribs |= FILE_ATTRIBUTE_DIRECTORY;
862 AFSAcquireShared( &pFcb->NPFcb->Resource,
867 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
868 AFS_TRACE_LEVEL_VERBOSE_2,
869 "AFSQueryBasicInfo %wZ Type 0x%x Attrib 0x%x -> 0x%x\n",
870 &pCcb->DirectoryCB->NameInformation.FileName,
871 pCcb->DirectoryCB->ObjectInformation->FileType,
872 pCcb->DirectoryCB->ObjectInformation->FileAttributes,
875 Buffer->CreationTime = DirectoryCB->ObjectInformation->CreationTime;
876 Buffer->LastAccessTime = DirectoryCB->ObjectInformation->LastAccessTime;
877 Buffer->LastWriteTime = DirectoryCB->ObjectInformation->LastWriteTime;
878 Buffer->ChangeTime = DirectoryCB->ObjectInformation->ChangeTime;
879 Buffer->FileAttributes = ulFileAttribs;
881 if( DirectoryCB->NameInformation.FileName.Buffer[ 0] == L'.' &&
882 BooleanFlagOn( pDeviceExt->DeviceFlags, AFS_DEVICE_FLAG_HIDE_DOT_NAMES))
885 if ( Buffer->FileAttributes != FILE_ATTRIBUTE_NORMAL)
887 Buffer->FileAttributes |= FILE_ATTRIBUTE_HIDDEN;
891 Buffer->FileAttributes = FILE_ATTRIBUTE_HIDDEN;
895 *Length -= sizeof( FILE_BASIC_INFORMATION);
900 ntStatus = STATUS_BUFFER_TOO_SMALL;
907 AFSQueryStandardInfo( IN PIRP Irp,
908 IN AFSDirectoryCB *DirectoryCB,
909 IN OUT PFILE_STANDARD_INFORMATION Buffer,
913 NTSTATUS ntStatus = STATUS_SUCCESS;
916 PIO_STACK_LOCATION pIrpSp = IoGetCurrentIrpStackLocation( Irp);
917 AFSFileInfoCB stFileInfo;
918 AFSDirectoryCB *pParentDirectoryCB = NULL;
919 UNICODE_STRING uniParentPath;
920 ULONG ulFileAttribs = 0;
922 if( *Length >= sizeof( FILE_STANDARD_INFORMATION))
925 pFcb = (AFSFcb *)pIrpSp->FileObject->FsContext;
926 pCcb = (AFSCcb *)pIrpSp->FileObject->FsContext2;
928 RtlZeroMemory( Buffer,
931 Buffer->NumberOfLinks = 1;
932 Buffer->DeletePending = BooleanFlagOn( pCcb->DirectoryCB->Flags, AFS_DIR_ENTRY_PENDING_DELETE);
934 Buffer->AllocationSize.QuadPart = (ULONGLONG)((DirectoryCB->ObjectInformation->AllocationSize.QuadPart/PAGE_SIZE) + 1) * PAGE_SIZE;
936 Buffer->EndOfFile = DirectoryCB->ObjectInformation->EndOfFile;
938 ulFileAttribs = DirectoryCB->ObjectInformation->FileAttributes;
940 if( DirectoryCB->ObjectInformation->FileType == AFS_FILE_TYPE_SYMLINK)
943 pParentDirectoryCB = AFSGetParentEntry( pCcb->NameArray);
945 AFSRetrieveParentPath( &pCcb->FullFileName,
948 RtlZeroMemory( &stFileInfo,
949 sizeof( AFSFileInfoCB));
952 // Can't hold the Fcb while evaluating the path, leads to lock inversion
955 AFSReleaseResource( &pFcb->NPFcb->Resource);
957 if( NT_SUCCESS( AFSRetrieveFileAttributes( pParentDirectoryCB,
965 if ( ulFileAttribs == FILE_ATTRIBUTE_NORMAL)
968 ulFileAttribs = FILE_ATTRIBUTE_REPARSE_POINT;
973 ulFileAttribs |= FILE_ATTRIBUTE_REPARSE_POINT;
976 if ( stFileInfo.FileAttributes & FILE_ATTRIBUTE_DIRECTORY)
979 ulFileAttribs |= FILE_ATTRIBUTE_DIRECTORY;
983 AFSAcquireShared( &pFcb->NPFcb->Resource,
987 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
988 AFS_TRACE_LEVEL_VERBOSE_2,
989 "AFSQueryStandardInfo %wZ Type 0x%x Attrib 0x%x -> 0x%x\n",
990 &pCcb->DirectoryCB->NameInformation.FileName,
991 pCcb->DirectoryCB->ObjectInformation->FileType,
992 pCcb->DirectoryCB->ObjectInformation->FileAttributes,
995 Buffer->Directory = BooleanFlagOn( ulFileAttribs, FILE_ATTRIBUTE_DIRECTORY);
997 *Length -= sizeof( FILE_STANDARD_INFORMATION);
1002 ntStatus = STATUS_BUFFER_TOO_SMALL;
1009 AFSQueryInternalInfo( IN PIRP Irp,
1011 IN OUT PFILE_INTERNAL_INFORMATION Buffer,
1012 IN OUT PLONG Length)
1015 NTSTATUS ntStatus = STATUS_SUCCESS;
1017 if( *Length >= sizeof( FILE_INTERNAL_INFORMATION))
1020 Buffer->IndexNumber.HighPart = Fcb->ObjectInformation->FileId.Volume;
1022 Buffer->IndexNumber.LowPart = Fcb->ObjectInformation->FileId.Vnode;
1024 *Length -= sizeof( FILE_INTERNAL_INFORMATION);
1029 ntStatus = STATUS_BUFFER_TOO_SMALL;
1036 AFSQueryEaInfo( IN PIRP Irp,
1037 IN AFSDirectoryCB *DirectoryCB,
1038 IN OUT PFILE_EA_INFORMATION Buffer,
1039 IN OUT PLONG Length)
1042 NTSTATUS ntStatus = STATUS_SUCCESS;
1044 RtlZeroMemory( Buffer,
1047 if( *Length >= sizeof( FILE_EA_INFORMATION))
1052 *Length -= sizeof( FILE_EA_INFORMATION);
1057 ntStatus = STATUS_BUFFER_TOO_SMALL;
1064 AFSQueryPositionInfo( IN PIRP Irp,
1066 IN OUT PFILE_POSITION_INFORMATION Buffer,
1067 IN OUT PLONG Length)
1070 NTSTATUS ntStatus = STATUS_SUCCESS;
1071 PIO_STACK_LOCATION pIrpSp = IoGetCurrentIrpStackLocation( Irp);
1073 if( *Length >= sizeof( FILE_POSITION_INFORMATION))
1076 RtlZeroMemory( Buffer,
1079 Buffer->CurrentByteOffset.QuadPart = pIrpSp->FileObject->CurrentByteOffset.QuadPart;
1081 *Length -= sizeof( FILE_POSITION_INFORMATION);
1086 ntStatus = STATUS_BUFFER_TOO_SMALL;
1093 AFSQueryAccess( IN PIRP Irp,
1095 IN OUT PFILE_ACCESS_INFORMATION Buffer,
1096 IN OUT PLONG Length)
1099 NTSTATUS ntStatus = STATUS_SUCCESS;
1101 if( *Length >= sizeof( FILE_ACCESS_INFORMATION))
1104 RtlZeroMemory( Buffer,
1107 Buffer->AccessFlags = 0;
1109 *Length -= sizeof( FILE_ACCESS_INFORMATION);
1114 ntStatus = STATUS_BUFFER_TOO_SMALL;
1121 AFSQueryMode( IN PIRP Irp,
1123 IN OUT PFILE_MODE_INFORMATION Buffer,
1124 IN OUT PLONG Length)
1127 NTSTATUS ntStatus = STATUS_SUCCESS;
1129 if( *Length >= sizeof( FILE_MODE_INFORMATION))
1132 RtlZeroMemory( Buffer,
1137 *Length -= sizeof( FILE_MODE_INFORMATION);
1142 ntStatus = STATUS_BUFFER_TOO_SMALL;
1149 AFSQueryAlignment( IN PIRP Irp,
1151 IN OUT PFILE_ALIGNMENT_INFORMATION Buffer,
1152 IN OUT PLONG Length)
1155 NTSTATUS ntStatus = STATUS_SUCCESS;
1157 if( *Length >= sizeof( FILE_ALIGNMENT_INFORMATION))
1160 RtlZeroMemory( Buffer,
1163 Buffer->AlignmentRequirement = 1;
1165 *Length -= sizeof( FILE_ALIGNMENT_INFORMATION);
1170 ntStatus = STATUS_BUFFER_TOO_SMALL;
1177 AFSQueryNameInfo( IN PIRP Irp,
1178 IN AFSDirectoryCB *DirectoryCB,
1179 IN OUT PFILE_NAME_INFORMATION Buffer,
1180 IN OUT PLONG Length)
1183 NTSTATUS ntStatus = STATUS_SUCCESS;
1184 ULONG ulCopyLength = 0;
1185 ULONG cchCopied = 0;
1186 AFSFcb *pFcb = NULL;
1187 AFSCcb *pCcb = NULL;
1188 IO_STACK_LOCATION *pIrpSp = IoGetCurrentIrpStackLocation( Irp);
1189 BOOLEAN bAddLeadingSlash = FALSE;
1190 BOOLEAN bAddTrailingSlash = FALSE;
1191 USHORT usFullNameLength = 0;
1193 pFcb = (AFSFcb *)pIrpSp->FileObject->FsContext;
1195 pCcb = (AFSCcb *)pIrpSp->FileObject->FsContext2;
1197 if( *Length >= FIELD_OFFSET( FILE_NAME_INFORMATION, FileName))
1200 RtlZeroMemory( Buffer,
1203 if( pCcb->FullFileName.Length == 0 ||
1204 pCcb->FullFileName.Buffer[ 0] != L'\\')
1206 bAddLeadingSlash = TRUE;
1209 if( pFcb->ObjectInformation->FileType == AFS_FILE_TYPE_DIRECTORY &&
1210 pCcb->FullFileName.Length > 0 &&
1211 pCcb->FullFileName.Buffer[ (pCcb->FullFileName.Length/sizeof( WCHAR)) - 1] != L'\\')
1213 bAddTrailingSlash = TRUE;
1216 usFullNameLength = sizeof( WCHAR) +
1217 AFSServerName.Length +
1218 pCcb->FullFileName.Length;
1220 if( bAddLeadingSlash)
1222 usFullNameLength += sizeof( WCHAR);
1225 if( bAddTrailingSlash)
1227 usFullNameLength += sizeof( WCHAR);
1230 if( *Length >= (LONG)(FIELD_OFFSET( FILE_NAME_INFORMATION, FileName) + (LONG)usFullNameLength))
1233 ulCopyLength = (LONG)usFullNameLength;
1238 ulCopyLength = *Length - FIELD_OFFSET( FILE_NAME_INFORMATION, FileName);
1240 ntStatus = STATUS_BUFFER_OVERFLOW;
1243 Buffer->FileNameLength = (ULONG)usFullNameLength;
1245 *Length -= FIELD_OFFSET( FILE_NAME_INFORMATION, FileName);
1247 if( ulCopyLength > 0)
1250 Buffer->FileName[ 0] = L'\\';
1251 ulCopyLength -= sizeof( WCHAR);
1253 *Length -= sizeof( WCHAR);
1256 if( ulCopyLength >= AFSServerName.Length)
1259 RtlCopyMemory( &Buffer->FileName[ 1],
1260 AFSServerName.Buffer,
1261 AFSServerName.Length);
1263 ulCopyLength -= AFSServerName.Length;
1264 *Length -= AFSServerName.Length;
1265 cchCopied += AFSServerName.Length/sizeof( WCHAR);
1267 if ( ulCopyLength > 0 &&
1271 Buffer->FileName[ cchCopied] = L'\\';
1273 ulCopyLength -= sizeof( WCHAR);
1274 *Length -= sizeof( WCHAR);
1278 if( ulCopyLength >= pCcb->FullFileName.Length)
1281 RtlCopyMemory( &Buffer->FileName[ cchCopied],
1282 pCcb->FullFileName.Buffer,
1283 pCcb->FullFileName.Length);
1285 ulCopyLength -= pCcb->FullFileName.Length;
1286 *Length -= pCcb->FullFileName.Length;
1287 cchCopied += pCcb->FullFileName.Length/sizeof( WCHAR);
1289 if( ulCopyLength > 0 &&
1292 Buffer->FileName[ cchCopied] = L'\\';
1294 *Length -= sizeof( WCHAR);
1300 RtlCopyMemory( &Buffer->FileName[ cchCopied],
1301 pCcb->FullFileName.Buffer,
1304 *Length -= ulCopyLength;
1312 ntStatus = STATUS_BUFFER_TOO_SMALL;
1319 AFSQueryShortNameInfo( IN PIRP Irp,
1320 IN AFSDirectoryCB *DirectoryCB,
1321 IN OUT PFILE_NAME_INFORMATION Buffer,
1322 IN OUT PLONG Length)
1325 NTSTATUS ntStatus = STATUS_BUFFER_TOO_SMALL;
1326 ULONG ulCopyLength = 0;
1328 RtlZeroMemory( Buffer,
1331 if( DirectoryCB->NameInformation.ShortNameLength == 0)
1335 // The short name IS the long name
1338 if( *Length >= (LONG)FIELD_OFFSET( FILE_NAME_INFORMATION, FileName))
1341 if( *Length >= (LONG)(FIELD_OFFSET( FILE_NAME_INFORMATION, FileName) + (LONG)DirectoryCB->NameInformation.FileName.Length))
1344 ulCopyLength = (LONG)DirectoryCB->NameInformation.FileName.Length;
1346 ntStatus = STATUS_SUCCESS;
1351 ulCopyLength = *Length - FIELD_OFFSET( FILE_NAME_INFORMATION, FileName);
1353 ntStatus = STATUS_BUFFER_OVERFLOW;
1356 Buffer->FileNameLength = DirectoryCB->NameInformation.FileName.Length;
1358 *Length -= FIELD_OFFSET( FILE_NAME_INFORMATION, FileName);
1360 if( ulCopyLength > 0)
1363 RtlCopyMemory( Buffer->FileName,
1364 DirectoryCB->NameInformation.FileName.Buffer,
1367 *Length -= ulCopyLength;
1374 if( *Length >= (LONG)FIELD_OFFSET( FILE_NAME_INFORMATION, FileName))
1377 if( *Length >= (LONG)(FIELD_OFFSET( FILE_NAME_INFORMATION, FileName) + (LONG)DirectoryCB->NameInformation.FileName.Length))
1380 ulCopyLength = (LONG)DirectoryCB->NameInformation.ShortNameLength;
1382 ntStatus = STATUS_SUCCESS;
1387 ulCopyLength = *Length - FIELD_OFFSET( FILE_NAME_INFORMATION, FileName);
1389 ntStatus = STATUS_BUFFER_OVERFLOW;
1392 Buffer->FileNameLength = DirectoryCB->NameInformation.ShortNameLength;
1394 *Length -= FIELD_OFFSET( FILE_NAME_INFORMATION, FileName);
1396 if( ulCopyLength > 0)
1399 RtlCopyMemory( Buffer->FileName,
1400 DirectoryCB->NameInformation.ShortName,
1401 Buffer->FileNameLength);
1403 *Length -= ulCopyLength;
1412 AFSQueryNetworkInfo( IN PIRP Irp,
1413 IN AFSDirectoryCB *DirectoryCB,
1414 IN OUT PFILE_NETWORK_OPEN_INFORMATION Buffer,
1415 IN OUT PLONG Length)
1418 NTSTATUS ntStatus = STATUS_SUCCESS;
1419 AFSDeviceExt *pDeviceExt = (AFSDeviceExt *)AFSRDRDeviceObject->DeviceExtension;
1420 AFSFcb *pFcb = NULL;
1421 AFSCcb *pCcb = NULL;
1422 PIO_STACK_LOCATION pIrpSp = IoGetCurrentIrpStackLocation( Irp);
1423 AFSFileInfoCB stFileInfo;
1424 AFSDirectoryCB *pParentDirectoryCB = NULL;
1425 UNICODE_STRING uniParentPath;
1426 ULONG ulFileAttribs = 0;
1428 RtlZeroMemory( Buffer,
1431 if( *Length >= sizeof( FILE_NETWORK_OPEN_INFORMATION))
1434 ulFileAttribs = DirectoryCB->ObjectInformation->FileAttributes;
1436 pFcb = (AFSFcb *)pIrpSp->FileObject->FsContext;
1437 pCcb = (AFSCcb *)pIrpSp->FileObject->FsContext2;
1439 if( DirectoryCB->ObjectInformation->FileType == AFS_FILE_TYPE_SYMLINK)
1442 pParentDirectoryCB = AFSGetParentEntry( pCcb->NameArray);
1444 AFSRetrieveParentPath( &pCcb->FullFileName,
1447 RtlZeroMemory( &stFileInfo,
1448 sizeof( AFSFileInfoCB));
1451 // Can't hold the Fcb while evaluating the path, leads to lock inversion
1454 AFSReleaseResource( &pFcb->NPFcb->Resource);
1456 if( NT_SUCCESS( AFSRetrieveFileAttributes( pParentDirectoryCB,
1464 if ( ulFileAttribs == FILE_ATTRIBUTE_NORMAL)
1467 ulFileAttribs = FILE_ATTRIBUTE_REPARSE_POINT;
1472 ulFileAttribs |= FILE_ATTRIBUTE_REPARSE_POINT;
1475 if ( stFileInfo.FileAttributes & FILE_ATTRIBUTE_DIRECTORY)
1478 ulFileAttribs |= FILE_ATTRIBUTE_DIRECTORY;
1482 AFSAcquireShared( &pFcb->NPFcb->Resource,
1486 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
1487 AFS_TRACE_LEVEL_VERBOSE_2,
1488 "AFSQueryNetworkInfo %wZ Type 0x%x Attrib 0x%x -> 0x%x\n",
1489 &pCcb->DirectoryCB->NameInformation.FileName,
1490 pCcb->DirectoryCB->ObjectInformation->FileType,
1491 pCcb->DirectoryCB->ObjectInformation->FileAttributes,
1494 Buffer->CreationTime.QuadPart = DirectoryCB->ObjectInformation->CreationTime.QuadPart;
1495 Buffer->LastAccessTime.QuadPart = DirectoryCB->ObjectInformation->LastAccessTime.QuadPart;
1496 Buffer->LastWriteTime.QuadPart = DirectoryCB->ObjectInformation->LastWriteTime.QuadPart;
1497 Buffer->ChangeTime.QuadPart = DirectoryCB->ObjectInformation->ChangeTime.QuadPart;
1499 Buffer->AllocationSize.QuadPart = DirectoryCB->ObjectInformation->AllocationSize.QuadPart;
1500 Buffer->EndOfFile.QuadPart = DirectoryCB->ObjectInformation->EndOfFile.QuadPart;
1502 Buffer->FileAttributes = ulFileAttribs;
1504 if( DirectoryCB->NameInformation.FileName.Buffer[ 0] == L'.' &&
1505 BooleanFlagOn( pDeviceExt->DeviceFlags, AFS_DEVICE_FLAG_HIDE_DOT_NAMES))
1508 if ( Buffer->FileAttributes != FILE_ATTRIBUTE_NORMAL)
1511 Buffer->FileAttributes |= FILE_ATTRIBUTE_HIDDEN;
1516 Buffer->FileAttributes = FILE_ATTRIBUTE_HIDDEN;
1520 *Length -= sizeof( FILE_NETWORK_OPEN_INFORMATION);
1525 ntStatus = STATUS_BUFFER_TOO_SMALL;
1532 AFSQueryStreamInfo( IN PIRP Irp,
1533 IN AFSDirectoryCB *DirectoryCB,
1534 IN OUT FILE_STREAM_INFORMATION *Buffer,
1535 IN OUT PLONG Length)
1538 NTSTATUS ntStatus = STATUS_BUFFER_TOO_SMALL;
1539 ULONG ulCopyLength = 0;
1540 AFSDeviceExt *pDeviceExt = (AFSDeviceExt *)AFSRDRDeviceObject->DeviceExtension;
1542 if( *Length >= FIELD_OFFSET( FILE_STREAM_INFORMATION, StreamName))
1545 RtlZeroMemory( Buffer,
1548 Buffer->NextEntryOffset = 0;
1551 if( !BooleanFlagOn( DirectoryCB->ObjectInformation->FileAttributes, FILE_ATTRIBUTE_DIRECTORY))
1554 if( *Length >= (LONG)(FIELD_OFFSET( FILE_STREAM_INFORMATION, StreamName) + 14)) // ::$DATA
1559 ntStatus = STATUS_SUCCESS;
1564 ulCopyLength = *Length - FIELD_OFFSET( FILE_STREAM_INFORMATION, StreamName);
1566 ntStatus = STATUS_BUFFER_OVERFLOW;
1569 Buffer->StreamNameLength = 14; // ::$DATA
1571 Buffer->StreamSize.QuadPart = DirectoryCB->ObjectInformation->EndOfFile.QuadPart;
1573 Buffer->StreamAllocationSize.QuadPart = DirectoryCB->ObjectInformation->AllocationSize.QuadPart;
1575 *Length -= FIELD_OFFSET( FILE_STREAM_INFORMATION, StreamName);
1577 if( ulCopyLength > 0)
1580 RtlCopyMemory( Buffer->StreamName,
1584 *Length -= ulCopyLength;
1590 Buffer->StreamNameLength = 0; // No stream for a directory
1592 // The response size is zero
1594 ntStatus = STATUS_SUCCESS;
1602 AFSQueryAttribTagInfo( IN PIRP Irp,
1603 IN AFSDirectoryCB *DirectoryCB,
1604 IN OUT FILE_ATTRIBUTE_TAG_INFORMATION *Buffer,
1605 IN OUT PLONG Length)
1608 NTSTATUS ntStatus = STATUS_BUFFER_TOO_SMALL;
1609 ULONG ulCopyLength = 0;
1610 AFSDeviceExt *pDeviceExt = (AFSDeviceExt *)AFSRDRDeviceObject->DeviceExtension;
1611 AFSFcb *pFcb = NULL;
1612 AFSCcb *pCcb = NULL;
1613 PIO_STACK_LOCATION pIrpSp = IoGetCurrentIrpStackLocation( Irp);
1614 AFSFileInfoCB stFileInfo;
1615 AFSDirectoryCB *pParentDirectoryCB = NULL;
1616 UNICODE_STRING uniParentPath;
1617 ULONG ulFileAttribs = 0;
1619 if( *Length >= sizeof( FILE_ATTRIBUTE_TAG_INFORMATION))
1622 RtlZeroMemory( Buffer,
1625 ulFileAttribs = DirectoryCB->ObjectInformation->FileAttributes;
1627 pFcb = (AFSFcb *)pIrpSp->FileObject->FsContext;
1628 pCcb = (AFSCcb *)pIrpSp->FileObject->FsContext2;
1630 if( DirectoryCB->ObjectInformation->FileType == AFS_FILE_TYPE_SYMLINK)
1633 pParentDirectoryCB = AFSGetParentEntry( pCcb->NameArray);
1635 AFSRetrieveParentPath( &pCcb->FullFileName,
1638 RtlZeroMemory( &stFileInfo,
1639 sizeof( AFSFileInfoCB));
1642 // Can't hold the Fcb while evaluating the path, leads to lock inversion
1645 AFSReleaseResource( &pFcb->NPFcb->Resource);
1647 if( NT_SUCCESS( AFSRetrieveFileAttributes( pParentDirectoryCB,
1655 if ( ulFileAttribs == FILE_ATTRIBUTE_NORMAL)
1658 ulFileAttribs = FILE_ATTRIBUTE_REPARSE_POINT;
1663 ulFileAttribs |= FILE_ATTRIBUTE_REPARSE_POINT;
1666 if ( stFileInfo.FileAttributes & FILE_ATTRIBUTE_DIRECTORY)
1669 ulFileAttribs |= FILE_ATTRIBUTE_DIRECTORY;
1673 AFSAcquireShared( &pFcb->NPFcb->Resource,
1677 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
1678 AFS_TRACE_LEVEL_VERBOSE_2,
1679 "AFSAttribTagInfo %wZ Type 0x%x Attrib 0x%x -> 0x%x\n",
1680 &pCcb->DirectoryCB->NameInformation.FileName,
1681 pCcb->DirectoryCB->ObjectInformation->FileType,
1682 pCcb->DirectoryCB->ObjectInformation->FileAttributes,
1685 Buffer->FileAttributes = ulFileAttribs;
1687 if( DirectoryCB->NameInformation.FileName.Buffer[ 0] == L'.' &&
1688 BooleanFlagOn( pDeviceExt->DeviceFlags, AFS_DEVICE_FLAG_HIDE_DOT_NAMES))
1691 if ( Buffer->FileAttributes != FILE_ATTRIBUTE_NORMAL)
1694 Buffer->FileAttributes |= FILE_ATTRIBUTE_HIDDEN;
1699 Buffer->FileAttributes = FILE_ATTRIBUTE_HIDDEN;
1703 if( BooleanFlagOn( DirectoryCB->ObjectInformation->FileAttributes, FILE_ATTRIBUTE_REPARSE_POINT))
1705 Buffer->ReparseTag = IO_REPARSE_TAG_SURROGATE|IO_REPARSE_TAG_OPENAFS_DFS;
1708 *Length -= sizeof( FILE_ATTRIBUTE_TAG_INFORMATION);
1710 ntStatus = STATUS_SUCCESS;
1717 AFSQueryRemoteProtocolInfo( IN PIRP Irp,
1718 IN AFSDirectoryCB *DirectoryCB,
1719 IN OUT FILE_REMOTE_PROTOCOL_INFORMATION *Buffer,
1720 IN OUT PLONG Length)
1723 NTSTATUS ntStatus = STATUS_BUFFER_TOO_SMALL;
1724 ULONG ulCopyLength = 0;
1725 AFSDeviceExt *pDeviceExt = (AFSDeviceExt *)AFSRDRDeviceObject->DeviceExtension;
1727 if( *Length >= sizeof( FILE_REMOTE_PROTOCOL_INFORMATION))
1730 RtlZeroMemory( Buffer,
1733 Buffer->StructureVersion = 1;
1735 Buffer->StructureSize = sizeof(FILE_REMOTE_PROTOCOL_INFORMATION);
1737 Buffer->Protocol = WNNC_NET_OPENAFS;
1739 Buffer->ProtocolMajorVersion = 3;
1741 Buffer->ProtocolMinorVersion = 0;
1743 Buffer->ProtocolRevision = 0;
1745 *Length -= sizeof( FILE_REMOTE_PROTOCOL_INFORMATION);
1747 ntStatus = STATUS_SUCCESS;
1754 AFSQueryPhysicalNameInfo( IN PIRP Irp,
1755 IN AFSDirectoryCB *DirectoryCB,
1756 IN OUT PFILE_NETWORK_PHYSICAL_NAME_INFORMATION Buffer,
1757 IN OUT PLONG Length)
1760 NTSTATUS ntStatus = STATUS_SUCCESS;
1761 ULONG ulCopyLength = 0;
1762 ULONG cchCopied = 0;
1763 AFSFcb *pFcb = NULL;
1764 AFSCcb *pCcb = NULL;
1765 IO_STACK_LOCATION *pIrpSp = IoGetCurrentIrpStackLocation( Irp);
1766 BOOLEAN bAddLeadingSlash = FALSE;
1767 USHORT usFullNameLength = 0;
1769 pFcb = (AFSFcb *)pIrpSp->FileObject->FsContext;
1771 pCcb = (AFSCcb *)pIrpSp->FileObject->FsContext2;
1773 if( *Length >= FIELD_OFFSET( FILE_NETWORK_PHYSICAL_NAME_INFORMATION, FileName))
1776 RtlZeroMemory( Buffer,
1779 if( pCcb->FullFileName.Length == 0 ||
1780 pCcb->FullFileName.Buffer[ 0] != L'\\')
1782 bAddLeadingSlash = TRUE;
1785 usFullNameLength = pCcb->FullFileName.Length;
1787 if( bAddLeadingSlash)
1789 usFullNameLength += sizeof( WCHAR);
1792 if( *Length >= (LONG)(FIELD_OFFSET( FILE_NETWORK_PHYSICAL_NAME_INFORMATION, FileName) + (LONG)usFullNameLength))
1794 ulCopyLength = (LONG)usFullNameLength;
1799 ulCopyLength = *Length - FIELD_OFFSET( FILE_NETWORK_PHYSICAL_NAME_INFORMATION, FileName);
1801 ntStatus = STATUS_BUFFER_OVERFLOW;
1804 Buffer->FileNameLength = (ULONG)usFullNameLength;
1806 *Length -= FIELD_OFFSET( FILE_NETWORK_PHYSICAL_NAME_INFORMATION, FileName);
1808 if( ulCopyLength > 0)
1811 if( bAddLeadingSlash)
1814 Buffer->FileName[ cchCopied] = L'\\';
1816 ulCopyLength -= sizeof( WCHAR);
1817 *Length -= sizeof( WCHAR);
1821 if( ulCopyLength >= pCcb->FullFileName.Length)
1824 RtlCopyMemory( &Buffer->FileName[ cchCopied],
1825 pCcb->FullFileName.Buffer,
1826 pCcb->FullFileName.Length);
1828 ulCopyLength -= pCcb->FullFileName.Length;
1829 *Length -= pCcb->FullFileName.Length;
1830 cchCopied += pCcb->FullFileName.Length/sizeof( WCHAR);
1835 RtlCopyMemory( &Buffer->FileName[ cchCopied],
1836 pCcb->FullFileName.Buffer,
1839 *Length -= ulCopyLength;
1846 ntStatus = STATUS_BUFFER_TOO_SMALL;
1853 AFSSetBasicInfo( IN PIRP Irp,
1854 IN AFSDirectoryCB *DirectoryCB)
1856 NTSTATUS ntStatus = STATUS_SUCCESS;
1857 PFILE_BASIC_INFORMATION pBuffer;
1858 PIO_STACK_LOCATION pIrpSp = IoGetCurrentIrpStackLocation( Irp);
1859 ULONG ulNotifyFilter = 0;
1860 AFSCcb *pCcb = NULL;
1865 pCcb = (AFSCcb *)pIrpSp->FileObject->FsContext2;
1867 pBuffer = (PFILE_BASIC_INFORMATION)Irp->AssociatedIrp.SystemBuffer;
1869 pCcb->FileUnwindInfo.FileAttributes = (ULONG)-1;
1871 if( pBuffer->FileAttributes != (ULONGLONG)0)
1874 if( DirectoryCB->ObjectInformation->Fcb->Header.NodeTypeCode == AFS_FILE_FCB &&
1875 BooleanFlagOn( pBuffer->FileAttributes, FILE_ATTRIBUTE_DIRECTORY))
1878 try_return( ntStatus = STATUS_INVALID_PARAMETER);
1881 if( DirectoryCB->ObjectInformation->Fcb->Header.NodeTypeCode == AFS_DIRECTORY_FCB)
1884 pBuffer->FileAttributes |= FILE_ATTRIBUTE_DIRECTORY;
1887 pCcb->FileUnwindInfo.FileAttributes = DirectoryCB->ObjectInformation->FileAttributes;
1889 DirectoryCB->ObjectInformation->FileAttributes = pBuffer->FileAttributes;
1891 ulNotifyFilter |= FILE_NOTIFY_CHANGE_ATTRIBUTES;
1893 SetFlag( DirectoryCB->ObjectInformation->Fcb->Flags, AFS_FCB_FLAG_FILE_MODIFIED);
1896 pCcb->FileUnwindInfo.CreationTime.QuadPart = (ULONGLONG)-1;
1898 if( pBuffer->CreationTime.QuadPart != (ULONGLONG)-1 &&
1899 pBuffer->CreationTime.QuadPart != (ULONGLONG)0)
1902 pCcb->FileUnwindInfo.CreationTime.QuadPart = DirectoryCB->ObjectInformation->CreationTime.QuadPart;
1904 DirectoryCB->ObjectInformation->CreationTime.QuadPart = pBuffer->CreationTime.QuadPart;
1906 ulNotifyFilter |= FILE_NOTIFY_CHANGE_CREATION;
1908 SetFlag( DirectoryCB->ObjectInformation->Fcb->Flags, AFS_FCB_FLAG_FILE_MODIFIED | AFS_FCB_FLAG_UPDATE_CREATE_TIME);
1911 pCcb->FileUnwindInfo.LastAccessTime.QuadPart = (ULONGLONG)-1;
1913 if( pBuffer->LastAccessTime.QuadPart != (ULONGLONG)-1 &&
1914 pBuffer->LastAccessTime.QuadPart != (ULONGLONG)0)
1917 pCcb->FileUnwindInfo.LastAccessTime.QuadPart = DirectoryCB->ObjectInformation->LastAccessTime.QuadPart;
1919 DirectoryCB->ObjectInformation->LastAccessTime.QuadPart = pBuffer->LastAccessTime.QuadPart;
1921 ulNotifyFilter |= FILE_NOTIFY_CHANGE_LAST_ACCESS;
1923 SetFlag( DirectoryCB->ObjectInformation->Fcb->Flags, AFS_FCB_FLAG_FILE_MODIFIED | AFS_FCB_FLAG_UPDATE_ACCESS_TIME);
1926 pCcb->FileUnwindInfo.LastWriteTime.QuadPart = (ULONGLONG)-1;
1928 if( pBuffer->LastWriteTime.QuadPart != (ULONGLONG)-1 &&
1929 pBuffer->LastWriteTime.QuadPart != (ULONGLONG)0)
1932 pCcb->FileUnwindInfo.LastWriteTime.QuadPart = DirectoryCB->ObjectInformation->LastWriteTime.QuadPart;
1934 DirectoryCB->ObjectInformation->LastWriteTime.QuadPart = pBuffer->LastWriteTime.QuadPart;
1936 ulNotifyFilter |= FILE_NOTIFY_CHANGE_LAST_WRITE;
1938 SetFlag( DirectoryCB->ObjectInformation->Fcb->Flags, AFS_FCB_FLAG_FILE_MODIFIED | AFS_FCB_FLAG_UPDATE_LAST_WRITE_TIME);
1941 pCcb->FileUnwindInfo.ChangeTime.QuadPart = (ULONGLONG)-1;
1943 if( pBuffer->ChangeTime.QuadPart != (ULONGLONG)-1 &&
1944 pBuffer->ChangeTime.QuadPart != (ULONGLONG)0)
1947 pCcb->FileUnwindInfo.ChangeTime.QuadPart = DirectoryCB->ObjectInformation->ChangeTime.QuadPart;
1949 DirectoryCB->ObjectInformation->ChangeTime.QuadPart = pBuffer->ChangeTime.QuadPart;
1951 ulNotifyFilter |= FILE_NOTIFY_CHANGE_LAST_ACCESS;
1953 SetFlag( DirectoryCB->ObjectInformation->Fcb->Flags, AFS_FCB_FLAG_FILE_MODIFIED | AFS_FCB_FLAG_UPDATE_CHANGE_TIME);
1956 if( ulNotifyFilter > 0)
1959 if( DirectoryCB->ObjectInformation->ParentObjectInformation != NULL)
1962 AFSFsRtlNotifyFullReportChange( DirectoryCB->ObjectInformation->ParentObjectInformation,
1964 (ULONG)ulNotifyFilter,
1965 (ULONG)FILE_ACTION_MODIFIED);
1978 AFSSetDispositionInfo( IN PIRP Irp,
1979 IN AFSDirectoryCB *DirectoryCB)
1981 NTSTATUS ntStatus = STATUS_SUCCESS;
1982 PFILE_DISPOSITION_INFORMATION pBuffer;
1983 PIO_STACK_LOCATION pIrpSp = IoGetCurrentIrpStackLocation( Irp);
1984 AFSFcb *pFcb = NULL;
1985 AFSCcb *pCcb = NULL;
1990 pBuffer = (PFILE_DISPOSITION_INFORMATION)Irp->AssociatedIrp.SystemBuffer;
1992 pFcb = (AFSFcb *)pIrpSp->FileObject->FsContext;
1994 pCcb = (AFSCcb *)pIrpSp->FileObject->FsContext2;
1997 // Can't delete the root
2000 if( pFcb->Header.NodeTypeCode == AFS_ROOT_FCB)
2003 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
2004 AFS_TRACE_LEVEL_ERROR,
2005 "AFSSetDispositionInfo Attempt to delete root entry\n");
2007 try_return( ntStatus = STATUS_CANNOT_DELETE);
2011 // If the file is read only then do not allow the delete
2014 if( BooleanFlagOn( DirectoryCB->ObjectInformation->FileAttributes, FILE_ATTRIBUTE_READONLY))
2017 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
2018 AFS_TRACE_LEVEL_ERROR,
2019 "AFSSetDispositionInfo Attempt to delete read only entry %wZ\n",
2020 &DirectoryCB->NameInformation.FileName);
2022 try_return( ntStatus = STATUS_CANNOT_DELETE);
2025 if( pBuffer->DeleteFile)
2029 // Check if the caller can delete the file
2032 ntStatus = AFSNotifyDelete( DirectoryCB,
2036 if( !NT_SUCCESS( ntStatus))
2039 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
2040 AFS_TRACE_LEVEL_ERROR,
2041 "AFSSetDispositionInfo Cannot delete entry %wZ Status %08lX\n",
2042 &DirectoryCB->NameInformation.FileName,
2045 try_return( ntStatus);
2048 if( pFcb->Header.NodeTypeCode == AFS_DIRECTORY_FCB)
2052 // Reduce the Link count in the object information block
2053 // to correspond with the deletion of the directory entry.
2056 pFcb->ObjectInformation->Links--;
2059 // Check if this is a directory that there are not currently other opens
2062 if( pFcb->ObjectInformation->Specific.Directory.ChildOpenHandleCount > 0)
2065 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
2066 AFS_TRACE_LEVEL_ERROR,
2067 "AFSSetDispositionInfo Attempt to delete directory %wZ with open %u handles\n",
2068 &DirectoryCB->NameInformation.FileName,
2069 pFcb->ObjectInformation->Specific.Directory.ChildOpenHandleCount);
2071 try_return( ntStatus = STATUS_DIRECTORY_NOT_EMPTY);
2074 if( !AFSIsDirectoryEmptyForDelete( pFcb))
2077 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
2078 AFS_TRACE_LEVEL_ERROR,
2079 "AFSSetDispositionInfo Attempt to delete non-empty directory %wZ\n",
2080 &DirectoryCB->NameInformation.FileName);
2082 try_return( ntStatus = STATUS_DIRECTORY_NOT_EMPTY);
2085 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
2086 AFS_TRACE_LEVEL_VERBOSE,
2087 "AFSSetDispositionInfo Setting PENDING_DELETE on DirEntry %p Name %wZ\n",
2089 &DirectoryCB->NameInformation.FileName);
2091 SetFlag( pCcb->DirectoryCB->Flags, AFS_DIR_ENTRY_PENDING_DELETE);
2093 else if( pFcb->Header.NodeTypeCode == AFS_FILE_FCB)
2097 // Attempt to flush any outstanding data
2100 if( !MmFlushImageSection( &pFcb->NPFcb->SectionObjectPointers,
2104 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
2105 AFS_TRACE_LEVEL_ERROR,
2106 "AFSSetDispositionInfo Failed to flush image section for delete Entry %wZ\n",
2107 &DirectoryCB->NameInformation.FileName);
2109 try_return( ntStatus = STATUS_CANNOT_DELETE);
2113 // Set PENDING_DELETE before CcPurgeCacheSection to avoid a
2114 // deadlock with Trend Micro's Enterprise anti-virus product
2115 // which attempts to open the file which is being deleted.
2118 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
2119 AFS_TRACE_LEVEL_VERBOSE,
2120 "AFSSetDispositionInfo Setting PENDING_DELETE on DirEntry %p Name %wZ\n",
2122 &DirectoryCB->NameInformation.FileName);
2124 SetFlag( pCcb->DirectoryCB->Flags, AFS_DIR_ENTRY_PENDING_DELETE);
2127 // Purge the cache as well
2130 if( pFcb->NPFcb->SectionObjectPointers.DataSectionObject != NULL)
2133 if ( !CcPurgeCacheSection( &pFcb->NPFcb->SectionObjectPointers,
2139 SetFlag( pFcb->Flags, AFS_FCB_FLAG_PURGE_ON_CLOSE);
2147 ClearFlag( pCcb->DirectoryCB->Flags, AFS_DIR_ENTRY_PENDING_DELETE);
2151 // OK, should be good to go, set the flag in the file object
2154 pIrpSp->FileObject->DeletePending = pBuffer->DeleteFile;
2165 AFSSetFileLinkInfo( IN PIRP Irp)
2168 NTSTATUS ntStatus = STATUS_SUCCESS;
2169 AFSDeviceExt *pDeviceExt = (AFSDeviceExt *)AFSRDRDeviceObject->DeviceExtension;
2170 PIO_STACK_LOCATION pIrpSp = IoGetCurrentIrpStackLocation( Irp);
2171 IO_STATUS_BLOCK stIoSb = {0,0};
2172 PFILE_LINK_INFORMATION pFileLinkInfo = NULL;
2173 PFILE_OBJECT pSrcFileObj = NULL;
2174 PFILE_OBJECT pTargetFileObj = pIrpSp->Parameters.SetFile.FileObject;
2175 AFSFcb *pSrcFcb = NULL, *pTargetDcb = NULL, *pTargetFcb = NULL;
2176 AFSCcb *pSrcCcb = NULL, *pTargetDirCcb = NULL;
2177 AFSObjectInfoCB *pSrcObject = NULL, *pTargetObject = NULL;
2178 AFSObjectInfoCB *pSrcParentObject = NULL, *pTargetParentObject = NULL;
2179 UNICODE_STRING uniSourceName, uniTargetName;
2180 UNICODE_STRING uniFullTargetName, uniTargetParentName;
2181 UNICODE_STRING uniShortName;
2182 BOOLEAN bCommonParent = FALSE;
2183 AFSDirectoryCB *pTargetDirEntry = NULL;
2184 AFSDirectoryCB *pNewTargetDirEntry = NULL;
2186 BOOLEAN bTargetEntryExists = FALSE;
2188 BOOLEAN bReleaseTargetDirLock = FALSE;
2190 ULONG ulNotificationAction = 0, ulNotifyFilter = 0;
2195 pSrcFileObj = pIrpSp->FileObject;
2197 pSrcFcb = (AFSFcb *)pSrcFileObj->FsContext;
2198 pSrcCcb = (AFSCcb *)pSrcFileObj->FsContext2;
2200 pSrcObject = pSrcFcb->ObjectInformation;
2201 pSrcParentObject = pSrcFcb->ObjectInformation->ParentObjectInformation;
2203 pFileLinkInfo = (PFILE_LINK_INFORMATION)Irp->AssociatedIrp.SystemBuffer;
2206 // Perform some basic checks to ensure FS integrity
2209 if( pSrcFcb->Header.NodeTypeCode != AFS_FILE_FCB)
2212 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
2213 AFS_TRACE_LEVEL_ERROR,
2214 "AFSSetFileLinkInfo Attempt to non-file (INVALID_PARAMETER)\n");
2216 try_return( ntStatus = STATUS_INVALID_PARAMETER);
2219 if( pTargetFileObj == NULL)
2222 if ( pFileLinkInfo->RootDirectory)
2226 // The target directory is provided by HANDLE
2227 // RootDirectory is only set when the target directory is not the same
2228 // as the source directory.
2230 // AFS only supports hard links within a single directory.
2232 // The IOManager should translate any Handle to a FileObject for us.
2233 // However, the failure to receive a FileObject is treated as a fatal
2237 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
2238 AFS_TRACE_LEVEL_ERROR,
2239 "AFSSetFileLinkInfo Attempt to link %wZ to alternate directory by handle INVALID_PARAMETER\n",
2240 &pSrcCcb->DirectoryCB->NameInformation.FileName);
2242 try_return( ntStatus = STATUS_INVALID_PARAMETER);
2247 uniFullTargetName.Length = (USHORT)pFileLinkInfo->FileNameLength;
2249 uniFullTargetName.Buffer = (PWSTR)&pFileLinkInfo->FileName;
2251 AFSRetrieveFinalComponent( &uniFullTargetName,
2254 AFSRetrieveParentPath( &uniFullTargetName,
2255 &uniTargetParentName);
2257 if ( uniTargetParentName.Length == 0)
2261 // This is a simple rename. Here the target directory is the same as the source parent directory
2262 // and the name is retrieved from the system buffer information
2265 pTargetParentObject = pSrcParentObject;
2270 // uniTargetParentName contains the directory the renamed object
2271 // will be moved to. Must obtain the TargetParentObject.
2274 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
2275 AFS_TRACE_LEVEL_ERROR,
2276 "AFSSetFileLinkInfo Attempt to link %wZ to alternate directory %wZ (NOT_SAME_DEVICE)\n",
2277 &pSrcCcb->DirectoryCB->NameInformation.FileName,
2278 &uniFullTargetName);
2280 try_return( ntStatus = STATUS_NOT_SAME_DEVICE);
2284 pTargetDcb = pTargetParentObject->Fcb;
2290 // So here we have the target directory taken from the targetfile object
2293 pTargetDcb = (AFSFcb *)pTargetFileObj->FsContext;
2295 pTargetDirCcb = (AFSCcb *)pTargetFileObj->FsContext2;
2297 pTargetParentObject = (AFSObjectInfoCB *)pTargetDcb->ObjectInformation;
2300 // Grab the target name which we setup in the IRP_MJ_CREATE handler. By how we set this up
2301 // it is only the target component of the rename operation
2304 uniTargetName = *((PUNICODE_STRING)&pTargetFileObj->FileName);
2308 // The quick check to see if they are self linking.
2309 // Do the names match? Only do this where the parent directories are
2313 if( pTargetParentObject == pSrcParentObject)
2316 if( FsRtlAreNamesEqual( &uniTargetName,
2321 try_return( ntStatus = STATUS_SUCCESS);
2324 bCommonParent = TRUE;
2330 // We do not allow cross-volume hard links
2333 if( pTargetParentObject->VolumeCB != pSrcObject->VolumeCB)
2336 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
2337 AFS_TRACE_LEVEL_ERROR,
2338 "AFSSetFileLinkInfo Attempt to link to different volume %wZ\n",
2339 &pSrcCcb->DirectoryCB->NameInformation.FileName);
2341 try_return( ntStatus = STATUS_NOT_SAME_DEVICE);
2345 ulTargetCRC = AFSGenerateCRC( &uniTargetName,
2348 AFSAcquireExcl( pTargetParentObject->Specific.Directory.DirectoryNodeHdr.TreeLock,
2351 bReleaseTargetDirLock = TRUE;
2353 AFSLocateCaseSensitiveDirEntry( pTargetParentObject->Specific.Directory.DirectoryNodeHdr.CaseSensitiveTreeHead,
2357 if( pTargetDirEntry == NULL)
2361 // Missed so perform a case insensitive lookup
2364 ulTargetCRC = AFSGenerateCRC( &uniTargetName,
2367 AFSLocateCaseInsensitiveDirEntry( pTargetParentObject->Specific.Directory.DirectoryNodeHdr.CaseInsensitiveTreeHead,
2372 if ( !BooleanFlagOn( pDeviceExt->DeviceFlags, AFS_DEVICE_FLAG_DISABLE_SHORTNAMES) &&
2373 pTargetDirEntry == NULL && RtlIsNameLegalDOS8Dot3( &uniTargetName,
2378 // Try the short name
2380 AFSLocateShortNameDirEntry( pTargetParentObject->Specific.Directory.ShortNameTree,
2386 // Increment our ref count on the dir entry
2389 if( pTargetDirEntry != NULL)
2392 ASSERT( pTargetParentObject == pTargetDirEntry->ObjectInformation->ParentObjectInformation);
2394 lCount = InterlockedIncrement( &pTargetDirEntry->DirOpenReferenceCount);
2396 AFSDbgLogMsg( AFS_SUBSYSTEM_DIRENTRY_REF_COUNTING,
2397 AFS_TRACE_LEVEL_VERBOSE,
2398 "AFSSetFileLinkInfo Increment count on %wZ DE %p Ccb %p Cnt %d\n",
2399 &pTargetDirEntry->NameInformation.FileName,
2404 ASSERT( lCount >= 0);
2406 if( !pFileLinkInfo->ReplaceIfExists)
2409 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
2410 AFS_TRACE_LEVEL_ERROR,
2411 "AFSSetFileLinkInfo Attempt to link with target collision %wZ Target %wZ\n",
2412 &pSrcCcb->DirectoryCB->NameInformation.FileName,
2413 &pTargetDirEntry->NameInformation.FileName);
2415 try_return( ntStatus = STATUS_OBJECT_NAME_COLLISION);
2418 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING | AFS_SUBSYSTEM_DIRENTRY_REF_COUNTING,
2419 AFS_TRACE_LEVEL_ERROR,
2420 "AFSSetFileLinkInfo Target %wZ exists DE %p Count %08lX, performing delete of target\n",
2421 &pTargetDirEntry->NameInformation.FileName,
2423 pTargetDirEntry->DirOpenReferenceCount);
2426 // Pull the directory entry from the parent
2429 AFSRemoveDirNodeFromParent( pTargetParentObject,
2433 bTargetEntryExists = TRUE;
2437 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
2438 AFS_TRACE_LEVEL_VERBOSE,
2439 "AFSSetFileLinkInfo Target does NOT exist, normal linking\n");
2443 // OK, this is a simple rename. Issue the rename
2444 // request to the service.
2447 ntStatus = AFSNotifyHardLink( pSrcFcb->ObjectInformation,
2448 &pSrcCcb->AuthGroup,
2449 pSrcFcb->ObjectInformation->ParentObjectInformation,
2450 pTargetDcb->ObjectInformation,
2451 pSrcCcb->DirectoryCB,
2453 pFileLinkInfo->ReplaceIfExists,
2454 &pNewTargetDirEntry);
2456 if( !NT_SUCCESS( ntStatus))
2459 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
2460 AFS_TRACE_LEVEL_ERROR,
2461 "AFSSetFileLinkInfo Failed link of %wZ to target %wZ Status %08lX\n",
2462 &pSrcCcb->DirectoryCB->NameInformation.FileName,
2466 try_return( ntStatus);
2469 AFSInsertDirectoryNode( pTargetDcb->ObjectInformation,
2474 // Send notification for the target link file
2477 if( bTargetEntryExists || pNewTargetDirEntry)
2480 ulNotificationAction = FILE_ACTION_MODIFIED;
2485 ulNotificationAction = FILE_ACTION_ADDED;
2488 AFSFsRtlNotifyFullReportChange( pTargetParentObject->ParentObjectInformation,
2490 (ULONG)ulNotifyFilter,
2491 (ULONG)ulNotificationAction);
2495 if( !NT_SUCCESS( ntStatus))
2498 if( bTargetEntryExists)
2501 AFSInsertDirectoryNode( pTargetDirEntry->ObjectInformation->ParentObjectInformation,
2507 if( pTargetDirEntry != NULL)
2510 lCount = InterlockedDecrement( &pTargetDirEntry->DirOpenReferenceCount);
2512 AFSDbgLogMsg( AFS_SUBSYSTEM_DIRENTRY_REF_COUNTING,
2513 AFS_TRACE_LEVEL_VERBOSE,
2514 "AFSSetFileLinkInfo Decrement count on %wZ DE %p Ccb %p Cnt %d\n",
2515 &pTargetDirEntry->NameInformation.FileName,
2520 ASSERT( lCount >= 0);
2523 if( bReleaseTargetDirLock)
2526 AFSReleaseResource( pTargetParentObject->Specific.Directory.DirectoryNodeHdr.TreeLock);
2534 AFSSetRenameInfo( IN PIRP Irp)
2537 NTSTATUS ntStatus = STATUS_SUCCESS;
2538 AFSDeviceExt *pDeviceExt = (AFSDeviceExt *)AFSRDRDeviceObject->DeviceExtension;
2539 PIO_STACK_LOCATION pIrpSp = IoGetCurrentIrpStackLocation( Irp);
2540 IO_STATUS_BLOCK stIoSb = {0,0};
2541 AFSFcb *pSrcFcb = NULL, *pTargetDcb = NULL, *pTargetFcb = NULL;
2542 AFSCcb *pSrcCcb = NULL, *pTargetDirCcb = NULL;
2543 PFILE_OBJECT pSrcFileObj = pIrpSp->FileObject;
2544 PFILE_OBJECT pTargetFileObj = pIrpSp->Parameters.SetFile.FileObject;
2545 PFILE_OBJECT pTargetParentFileObj = NULL;
2546 PFILE_RENAME_INFORMATION pRenameInfo = NULL;
2547 UNICODE_STRING uniTargetName, uniSourceName, uniTargetParentName;
2548 BOOLEAN bReplaceIfExists = FALSE;
2549 UNICODE_STRING uniShortName;
2550 AFSDirectoryCB *pTargetDirEntry = NULL;
2551 ULONG ulTargetCRC = 0;
2552 BOOLEAN bTargetEntryExists = FALSE;
2553 AFSObjectInfoCB *pSrcObject = NULL, *pTargetObject = NULL;
2554 AFSObjectInfoCB *pSrcParentObject = NULL, *pTargetParentObject = NULL;
2555 AFSFileID stNewFid, stTmpTargetFid;
2556 ULONG ulNotificationAction = 0, ulNotifyFilter = 0;
2557 UNICODE_STRING uniFullTargetName;
2558 BOOLEAN bCommonParent = FALSE;
2559 BOOLEAN bReleaseTargetDirLock = FALSE;
2560 BOOLEAN bReleaseSourceDirLock = FALSE;
2561 BOOLEAN bDereferenceTargetParentObject = FALSE;
2562 PERESOURCE pSourceDirLock = NULL;
2568 bReplaceIfExists = pIrpSp->Parameters.SetFile.ReplaceIfExists;
2570 pRenameInfo = (PFILE_RENAME_INFORMATION)Irp->AssociatedIrp.SystemBuffer;
2572 pSrcFcb = (AFSFcb *)pSrcFileObj->FsContext;
2573 pSrcCcb = (AFSCcb *)pSrcFileObj->FsContext2;
2575 pSrcObject = pSrcFcb->ObjectInformation;
2576 pSrcParentObject = pSrcFcb->ObjectInformation->ParentObjectInformation;
2579 // Perform some basic checks to ensure FS integrity
2582 if( pSrcFcb->Header.NodeTypeCode == AFS_ROOT_FCB)
2586 // Can't rename the root directory
2589 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
2590 AFS_TRACE_LEVEL_ERROR,
2591 "AFSSetRenameInfo Attempt to rename root entry\n");
2593 try_return( ntStatus = STATUS_INVALID_PARAMETER);
2596 if( pSrcFcb->Header.NodeTypeCode == AFS_DIRECTORY_FCB)
2600 // If there are any open children then fail the rename
2603 if( pSrcFcb->ObjectInformation->Specific.Directory.ChildOpenHandleCount > 0)
2606 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
2607 AFS_TRACE_LEVEL_ERROR,
2608 "AFSSetRenameInfo Attempt to rename directory with open children %wZ\n",
2609 &pSrcCcb->DirectoryCB->NameInformation.FileName);
2611 try_return( ntStatus = STATUS_ACCESS_DENIED);
2617 // Extract off the final component name from the Fcb
2620 uniSourceName.Length = (USHORT)pSrcCcb->DirectoryCB->NameInformation.FileName.Length;
2621 uniSourceName.MaximumLength = uniSourceName.Length;
2623 uniSourceName.Buffer = pSrcCcb->DirectoryCB->NameInformation.FileName.Buffer;
2626 // Resolve the target fileobject
2629 if( pTargetFileObj == NULL)
2632 if ( pRenameInfo->RootDirectory)
2635 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
2636 AFS_TRACE_LEVEL_ERROR,
2637 "AFSSetRenameInfo Handle provided but no FileObject ntStatus INVALID_PARAMETER\n");
2639 try_return( ntStatus = STATUS_INVALID_PARAMETER);
2644 uniFullTargetName.Length = (USHORT)pRenameInfo->FileNameLength;
2646 uniFullTargetName.Buffer = (PWSTR)&pRenameInfo->FileName;
2648 AFSRetrieveFinalComponent( &uniFullTargetName,
2651 AFSRetrieveParentPath( &uniFullTargetName,
2652 &uniTargetParentName);
2654 if ( uniTargetParentName.Length == 0)
2658 // This is a simple rename. Here the target directory is the same as the source parent directory
2659 // and the name is retrieved from the system buffer information
2662 pTargetParentObject = pSrcParentObject;
2667 // uniTargetParentName contains the directory the renamed object
2668 // will be moved to. Must obtain the TargetParentObject.
2671 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
2672 AFS_TRACE_LEVEL_ERROR,
2673 "AFSSetRenameInfo Attempt to move %wZ to %wZ -- not yet supported (NOT_SAME_DEVICE)\n",
2674 &pSrcCcb->DirectoryCB->NameInformation.FileName,
2675 &uniFullTargetName);
2677 try_return( ntStatus = STATUS_NOT_SAME_DEVICE);
2681 pTargetDcb = pTargetParentObject->Fcb;
2687 // So here we have the target directory taken from the targetfile object
2690 pTargetDcb = (AFSFcb *)pTargetFileObj->FsContext;
2692 pTargetDirCcb = (AFSCcb *)pTargetFileObj->FsContext2;
2694 pTargetParentObject = (AFSObjectInfoCB *)pTargetDcb->ObjectInformation;
2697 // Grab the target name which we setup in the IRP_MJ_CREATE handler. By how we set this up
2698 // it is only the target component of the rename operation
2701 uniTargetName = *((PUNICODE_STRING)&pTargetFileObj->FileName);
2705 // The quick check to see if they are not really performing a rename
2706 // Do the names match? Only do this where the parent directories are
2710 if( pTargetParentObject == pSrcParentObject)
2713 if( FsRtlAreNamesEqual( &uniTargetName,
2718 try_return( ntStatus = STATUS_SUCCESS);
2721 bCommonParent = TRUE;
2726 bCommonParent = FALSE;
2730 // We do not allow cross-volume renames to occur
2733 if( pTargetParentObject->VolumeCB != pSrcObject->VolumeCB)
2736 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
2737 AFS_TRACE_LEVEL_ERROR,
2738 "AFSSetRenameInfo Attempt to rename directory to different volume %wZ\n",
2739 &pSrcCcb->DirectoryCB->NameInformation.FileName);
2741 try_return( ntStatus = STATUS_NOT_SAME_DEVICE);
2744 ulTargetCRC = AFSGenerateCRC( &uniTargetName,
2747 AFSAcquireExcl( pTargetParentObject->Specific.Directory.DirectoryNodeHdr.TreeLock,
2750 bReleaseTargetDirLock = TRUE;
2752 if( pTargetParentObject != pSrcParentObject)
2754 AFSAcquireExcl( pSrcParentObject->Specific.Directory.DirectoryNodeHdr.TreeLock,
2757 bReleaseSourceDirLock = TRUE;
2759 pSourceDirLock = pSrcParentObject->Specific.Directory.DirectoryNodeHdr.TreeLock;
2762 AFSLocateCaseSensitiveDirEntry( pTargetParentObject->Specific.Directory.DirectoryNodeHdr.CaseSensitiveTreeHead,
2766 if( pTargetDirEntry == NULL)
2770 // Missed so perform a case insensitive lookup
2773 ulTargetCRC = AFSGenerateCRC( &uniTargetName,
2776 AFSLocateCaseInsensitiveDirEntry( pTargetParentObject->Specific.Directory.DirectoryNodeHdr.CaseInsensitiveTreeHead,
2781 if ( !BooleanFlagOn( pDeviceExt->DeviceFlags, AFS_DEVICE_FLAG_DISABLE_SHORTNAMES) &&
2782 pTargetDirEntry == NULL && RtlIsNameLegalDOS8Dot3( &uniTargetName,
2787 // Try the short name
2789 AFSLocateShortNameDirEntry( pTargetParentObject->Specific.Directory.ShortNameTree,
2795 // Increment our ref count on the dir entry
2798 if( pTargetDirEntry != NULL)
2801 ASSERT( pTargetParentObject == pTargetDirEntry->ObjectInformation->ParentObjectInformation);
2803 lCount = InterlockedIncrement( &pTargetDirEntry->DirOpenReferenceCount);
2806 AFSDbgLogMsg( AFS_SUBSYSTEM_DIRENTRY_REF_COUNTING,
2807 AFS_TRACE_LEVEL_VERBOSE,
2808 "AFSSetRenameInfo Increment count on %wZ DE %p Ccb %p Cnt %d\n",
2809 &pTargetDirEntry->NameInformation.FileName,
2814 ASSERT( lCount >= 0);
2816 if( !bReplaceIfExists)
2819 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
2820 AFS_TRACE_LEVEL_ERROR,
2821 "AFSSetRenameInfo Attempt to rename directory with target collision %wZ Target %wZ\n",
2822 &pSrcCcb->DirectoryCB->NameInformation.FileName,
2823 &pTargetDirEntry->NameInformation.FileName);
2825 try_return( ntStatus = STATUS_OBJECT_NAME_COLLISION);
2828 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING | AFS_SUBSYSTEM_DIRENTRY_REF_COUNTING,
2829 AFS_TRACE_LEVEL_ERROR,
2830 "AFSSetRenameInfo Target %wZ exists DE %p Count %08lX, performing delete of target\n",
2831 &pTargetDirEntry->NameInformation.FileName,
2833 pTargetDirEntry->DirOpenReferenceCount);
2836 // Pull the directory entry from the parent
2839 AFSRemoveDirNodeFromParent( pTargetParentObject,
2843 bTargetEntryExists = TRUE;
2847 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
2848 AFS_TRACE_LEVEL_VERBOSE,
2849 "AFSSetRenameInfo Target does NOT exist, normal rename\n");
2853 // We need to remove the DirEntry from the parent node, update the index
2854 // and reinsert it into the parent tree. Note that for entries with the
2855 // same parent we do not pull the node from the enumeration list
2858 AFSRemoveDirNodeFromParent( pSrcFcb->ObjectInformation->ParentObjectInformation,
2859 pSrcCcb->DirectoryCB,
2863 // OK, this is a simple rename. Issue the rename
2864 // request to the service.
2867 ntStatus = AFSNotifyRename( pSrcFcb->ObjectInformation,
2868 &pSrcCcb->AuthGroup,
2869 pSrcFcb->ObjectInformation->ParentObjectInformation,
2870 pTargetDcb->ObjectInformation,
2871 pSrcCcb->DirectoryCB,
2875 if( !NT_SUCCESS( ntStatus))
2879 // Attempt to re-insert the directory entry
2882 AFSInsertDirectoryNode( pSrcFcb->ObjectInformation->ParentObjectInformation,
2883 pSrcCcb->DirectoryCB,
2886 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
2887 AFS_TRACE_LEVEL_ERROR,
2888 "AFSSetRenameInfo Failed rename of %wZ to target %wZ Status %08lX\n",
2889 &pSrcCcb->DirectoryCB->NameInformation.FileName,
2893 try_return( ntStatus);
2897 // Set the notification up for the source file
2900 if( pSrcCcb->DirectoryCB->ObjectInformation->ParentObjectInformation == pTargetParentObject &&
2901 !bTargetEntryExists)
2904 ulNotificationAction = FILE_ACTION_RENAMED_OLD_NAME;
2909 ulNotificationAction = FILE_ACTION_REMOVED;
2912 if( pSrcCcb->DirectoryCB->ObjectInformation->FileType == AFS_FILE_TYPE_DIRECTORY)
2915 ulNotifyFilter = FILE_NOTIFY_CHANGE_DIR_NAME;
2920 ulNotifyFilter = FILE_NOTIFY_CHANGE_FILE_NAME;
2923 AFSFsRtlNotifyFullReportChange( pSrcCcb->DirectoryCB->ObjectInformation->ParentObjectInformation,
2925 (ULONG)ulNotifyFilter,
2926 (ULONG)ulNotificationAction);
2929 // Update the name in the dir entry.
2932 ntStatus = AFSUpdateDirEntryName( pSrcCcb->DirectoryCB,
2935 if( !NT_SUCCESS( ntStatus))
2939 // Attempt to re-insert the directory entry
2942 AFSInsertDirectoryNode( pSrcFcb->ObjectInformation->ParentObjectInformation,
2943 pSrcCcb->DirectoryCB,
2946 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
2947 AFS_TRACE_LEVEL_ERROR,
2948 "AFSSetRenameInfo Failed update of dir entry %wZ to target %wZ Status %08lX\n",
2949 &pSrcCcb->DirectoryCB->NameInformation.FileName,
2953 try_return( ntStatus);
2957 // Update the object information block, if needed
2960 if( !AFSIsEqualFID( &pSrcObject->FileId,
2964 AFSAcquireExcl( pSrcObject->VolumeCB->ObjectInfoTree.TreeLock,
2968 // Remove the old information entry
2971 AFSRemoveHashEntry( &pSrcObject->VolumeCB->ObjectInfoTree.TreeHead,
2972 &pSrcObject->TreeEntry);
2974 RtlCopyMemory( &pSrcObject->FileId,
2976 sizeof( AFSFileID));
2979 // Insert the entry into the new object table.
2982 pSrcObject->TreeEntry.HashIndex = AFSCreateLowIndex( &pSrcObject->FileId);
2984 if( pSrcObject->VolumeCB->ObjectInfoTree.TreeHead == NULL)
2987 pSrcObject->VolumeCB->ObjectInfoTree.TreeHead = &pSrcObject->TreeEntry;
2992 if ( !NT_SUCCESS( AFSInsertHashEntry( pSrcObject->VolumeCB->ObjectInfoTree.TreeHead,
2993 &pSrcObject->TreeEntry)))
2997 // Lost a race, an ObjectInfo object already exists for this FID.
2998 // Let this copy be garbage collected.
3001 ClearFlag( pSrcObject->Flags, AFS_OBJECT_INSERTED_HASH_TREE);
3005 AFSReleaseResource( pSrcObject->VolumeCB->ObjectInfoTree.TreeLock);
3009 // Update the hash values for the name trees.
3012 pSrcCcb->DirectoryCB->CaseSensitiveTreeEntry.HashIndex = AFSGenerateCRC( &pSrcCcb->DirectoryCB->NameInformation.FileName,
3015 pSrcCcb->DirectoryCB->CaseInsensitiveTreeEntry.HashIndex = AFSGenerateCRC( &pSrcCcb->DirectoryCB->NameInformation.FileName,
3018 if( !BooleanFlagOn( pDeviceExt->DeviceFlags, AFS_DEVICE_FLAG_DISABLE_SHORTNAMES) &&
3019 pSrcCcb->DirectoryCB->NameInformation.ShortNameLength > 0 &&
3020 !RtlIsNameLegalDOS8Dot3( &pSrcCcb->DirectoryCB->NameInformation.FileName,
3025 uniShortName.Length = pSrcCcb->DirectoryCB->NameInformation.ShortNameLength;
3026 uniShortName.MaximumLength = uniShortName.Length;
3027 uniShortName.Buffer = pSrcCcb->DirectoryCB->NameInformation.ShortName;
3029 pSrcCcb->DirectoryCB->Type.Data.ShortNameTreeEntry.HashIndex = AFSGenerateCRC( &uniShortName,
3032 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
3033 AFS_TRACE_LEVEL_VERBOSE,
3034 "AFSSetRenameInfo Initialized short name hash for %wZ longname %wZ\n",
3036 &pSrcCcb->DirectoryCB->NameInformation.FileName);
3041 pSrcCcb->DirectoryCB->Type.Data.ShortNameTreeEntry.HashIndex = 0;
3048 // Update the file index for the object in the new parent
3051 pSrcCcb->DirectoryCB->FileIndex = (ULONG)InterlockedIncrement( &pTargetParentObject->Specific.Directory.DirectoryNodeHdr.ContentIndex);
3055 // Re-insert the directory entry
3058 AFSInsertDirectoryNode( pTargetParentObject,
3059 pSrcCcb->DirectoryCB,
3063 // Update the parent pointer in the source object if they are different
3066 if( pSrcCcb->DirectoryCB->ObjectInformation->ParentObjectInformation != pTargetParentObject)
3069 lCount = InterlockedDecrement( &pSrcCcb->DirectoryCB->ObjectInformation->ParentObjectInformation->Specific.Directory.ChildOpenHandleCount);
3071 lCount = InterlockedDecrement( &pSrcCcb->DirectoryCB->ObjectInformation->ParentObjectInformation->Specific.Directory.ChildOpenReferenceCount);
3073 lCount = InterlockedIncrement( &pTargetParentObject->Specific.Directory.ChildOpenHandleCount);
3075 lCount = InterlockedIncrement( &pTargetParentObject->Specific.Directory.ChildOpenReferenceCount);
3077 pSrcCcb->DirectoryCB->ObjectInformation->ParentObjectInformation = pTargetParentObject;
3079 ulNotificationAction = FILE_ACTION_ADDED;
3084 ulNotificationAction = FILE_ACTION_RENAMED_NEW_NAME;
3088 // Now update the notification for the target file
3091 AFSFsRtlNotifyFullReportChange( pTargetParentObject->ParentObjectInformation,
3093 (ULONG)ulNotifyFilter,
3094 (ULONG)ulNotificationAction);
3097 // If we performed the rename of the target because it existed, we now need to
3098 // delete the tmp target we created above
3101 if( bTargetEntryExists)
3104 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
3105 AFS_TRACE_LEVEL_VERBOSE,
3106 "AFSSetRenameInfo Setting DELETE flag in dir entry %p name %wZ\n",
3108 &pTargetDirEntry->NameInformation.FileName);
3110 SetFlag( pTargetDirEntry->Flags, AFS_DIR_ENTRY_DELETED);
3113 // Try and purge the cache map if this is a file
3116 if( pTargetDirEntry->ObjectInformation->FileType == AFS_FILE_TYPE_FILE &&
3117 pTargetDirEntry->ObjectInformation->Fcb != NULL &&
3118 pTargetDirEntry->DirOpenReferenceCount > 1)
3121 pTargetFcb = pTargetDirEntry->ObjectInformation->Fcb;
3123 AFSAcquireExcl( &pTargetFcb->NPFcb->Resource,
3127 // Close the section in the event it was mapped
3130 if( !MmForceSectionClosed( &pTargetFcb->NPFcb->SectionObjectPointers,
3134 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
3135 AFS_TRACE_LEVEL_ERROR,
3136 "AFSSetRenameInfo Failed to delete section for target file %wZ\n",
3137 &pTargetDirEntry->NameInformation.FileName);
3140 AFSReleaseResource( &pTargetFcb->NPFcb->Resource);
3143 ASSERT( pTargetDirEntry->DirOpenReferenceCount > 0);
3145 lCount = InterlockedDecrement( &pTargetDirEntry->DirOpenReferenceCount); // The count we added above
3147 AFSDbgLogMsg( AFS_SUBSYSTEM_DIRENTRY_REF_COUNTING,
3148 AFS_TRACE_LEVEL_VERBOSE,
3149 "AFSSetRenameInfo Decrement count on %wZ DE %p Ccb %p Cnt %d\n",
3150 &pTargetDirEntry->NameInformation.FileName,
3155 ASSERT( lCount >= 0);
3160 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
3161 AFS_TRACE_LEVEL_VERBOSE,
3162 "AFSSetRenameInfo Deleting dir entry %p name %wZ\n",
3164 &pTargetDirEntry->NameInformation.FileName);
3166 AFSDeleteDirEntry( pTargetParentObject,
3170 pTargetDirEntry = NULL;
3175 if( !NT_SUCCESS( ntStatus))
3178 if( bTargetEntryExists)
3180 AFSInsertDirectoryNode( pTargetDirEntry->ObjectInformation->ParentObjectInformation,
3186 if( pTargetDirEntry != NULL)
3189 lCount = InterlockedDecrement( &pTargetDirEntry->DirOpenReferenceCount);
3191 AFSDbgLogMsg( AFS_SUBSYSTEM_DIRENTRY_REF_COUNTING,
3192 AFS_TRACE_LEVEL_VERBOSE,
3193 "AFSSetRenameInfo Decrement2 count on %wZ DE %p Ccb %p Cnt %d\n",
3194 &pTargetDirEntry->NameInformation.FileName,
3199 ASSERT( lCount >= 0);
3202 if( bReleaseTargetDirLock)
3204 AFSReleaseResource( pTargetParentObject->Specific.Directory.DirectoryNodeHdr.TreeLock);
3207 if( bReleaseSourceDirLock)
3209 AFSReleaseResource( pSourceDirLock);
3213 if ( bDereferenceTargetParentObject)
3216 ObDereferenceObject( pTargetParentFileObj);
3223 AFSSetPositionInfo( IN PIRP Irp,
3224 IN AFSDirectoryCB *DirectoryCB)
3226 NTSTATUS ntStatus = STATUS_SUCCESS;
3227 PFILE_POSITION_INFORMATION pBuffer;
3228 PIO_STACK_LOCATION pIrpSp = IoGetCurrentIrpStackLocation( Irp);
3230 pBuffer = (PFILE_POSITION_INFORMATION)Irp->AssociatedIrp.SystemBuffer;