X-Git-Url: https://git.openafs.org/?p=openafs.git;a=blobdiff_plain;f=src%2FWINNT%2Fafsrdr%2Fkernel%2Flib%2FAFSFSControl.cpp;h=d8a9d223f3e4f0b69c12a9f172ed337e31abc9de;hp=a8921668d00b2dec3254c302f4a2b1720aa91f44;hb=abbee864c48fb2e439c4141130ada184fad23db5;hpb=aaa1844b8f806513661d16c6429d4d1b890471f2 diff --git a/src/WINNT/afsrdr/kernel/lib/AFSFSControl.cpp b/src/WINNT/afsrdr/kernel/lib/AFSFSControl.cpp index a892166..d8a9d22 100644 --- a/src/WINNT/afsrdr/kernel/lib/AFSFSControl.cpp +++ b/src/WINNT/afsrdr/kernel/lib/AFSFSControl.cpp @@ -1,6 +1,6 @@ /* - * Copyright (c) 2008, 2009, 2010, 2011 Kernel Drivers, LLC. - * Copyright (c) 2009, 2010, 2011 Your File System, Inc. + * Copyright (c) 2008, 2009, 2010, 2011, 2012, 2013 Kernel Drivers, LLC. + * Copyright (c) 2009, 2010, 2011, 2012, 2013 Your File System, Inc. * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -10,10 +10,8 @@ * - Redistributions of source code must retain the above copyright notice, * this list of conditions and the following disclaimer. * - Redistributions in binary form must reproduce the above copyright - * notice, - * this list of conditions and the following disclaimer in the - * documentation - * and/or other materials provided with the distribution. + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. * - Neither the names of Kernel Drivers, LLC and Your File System, Inc. * nor the names of their contributors may be used to endorse or promote * products derived from this software without specific prior written @@ -43,6 +41,7 @@ AFSFSControl( IN PDEVICE_OBJECT LibDeviceObject, IN PIRP Irp) { + UNREFERENCED_PARAMETER(LibDeviceObject); NTSTATUS ntStatus = STATUS_SUCCESS; IO_STACK_LOCATION *pIrpSp; @@ -569,58 +568,231 @@ AFSProcessUserFsRequest( IN PIRP Irp) case FSCTL_SET_REPARSE_POINT: { - REPARSE_GUID_DATA_BUFFER *pReparseBuffer = (REPARSE_GUID_DATA_BUFFER *)Irp->AssociatedIrp.SystemBuffer; + REPARSE_GUID_DATA_BUFFER *pReparseGUIDBuffer = (REPARSE_GUID_DATA_BUFFER *)Irp->AssociatedIrp.SystemBuffer; + REPARSE_DATA_BUFFER *pReparseBuffer = NULL; + AFSReparseTagInfo *pReparseInfo = NULL; + AFSObjectInfoCB *pParentObjectInfo = NULL; + UNICODE_STRING uniTargetName; + ULONGLONG ullIndex = 0; + LONG lCount; AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING, - AFS_TRACE_LEVEL_VERBOSE_2, + AFS_TRACE_LEVEL_VERBOSE, "AFSProcessUserFsRequest Processing FSCTL_SET_REPARSE_POINT request %wZ Type 0x%x Attrib 0x%x\n", &pCcb->DirectoryCB->NameInformation.FileName, pCcb->DirectoryCB->ObjectInformation->FileType, pCcb->DirectoryCB->ObjectInformation->FileAttributes); - // - // Check if we have the reparse entry set on the entry - // - - if( !BooleanFlagOn( pCcb->DirectoryCB->ObjectInformation->FileAttributes, FILE_ATTRIBUTE_REPARSE_POINT)) + if( ulInputBufferLen < FIELD_OFFSET( REPARSE_GUID_DATA_BUFFER, GenericReparseBuffer.DataBuffer)) { - ntStatus = STATUS_NOT_A_REPARSE_POINT; + ntStatus = STATUS_IO_REPARSE_DATA_INVALID; break; } - if( ulInputBufferLen < FIELD_OFFSET( REPARSE_GUID_DATA_BUFFER, GenericReparseBuffer.DataBuffer)) + if( (pReparseGUIDBuffer->ReparseTag & 0x0000FFFF) == IO_REPARSE_TAG_OPENAFS_DFS) { - ntStatus = STATUS_IO_REPARSE_DATA_INVALID; + if( RtlCompareMemory( &pReparseGUIDBuffer->ReparseGuid, + &GUID_AFS_REPARSE_GUID, + sizeof( GUID)) != sizeof( GUID)) + { - break; - } + ntStatus = STATUS_REPARSE_ATTRIBUTE_CONFLICT; - if( (pReparseBuffer->ReparseTag & 0x0000FFFF) != IO_REPARSE_TAG_OPENAFS_DFS) + break; + } + + if( ulInputBufferLen < FIELD_OFFSET( REPARSE_GUID_DATA_BUFFER, GenericReparseBuffer.DataBuffer) + + sizeof( AFSReparseTagInfo)) + { + + ntStatus = STATUS_IO_REPARSE_DATA_INVALID; + + break; + } + + pReparseInfo = (AFSReparseTagInfo *)pReparseGUIDBuffer->GenericReparseBuffer.DataBuffer; + + switch( pReparseInfo->SubTag) + { + + case OPENAFS_SUBTAG_SYMLINK: + { + + if( ulInputBufferLen < (ULONG)(FIELD_OFFSET( REPARSE_GUID_DATA_BUFFER, GenericReparseBuffer.DataBuffer) + + FIELD_OFFSET( AFSReparseTagInfo, AFSSymLink.Buffer) + + pReparseInfo->AFSSymLink.SymLinkTargetLength)) + { + + ntStatus = STATUS_IO_REPARSE_DATA_INVALID; + + break; + } + + uniTargetName.Length = pReparseInfo->AFSSymLink.SymLinkTargetLength; + uniTargetName.MaximumLength = uniTargetName.Length; + + uniTargetName.Buffer = (WCHAR *)pReparseInfo->AFSSymLink.Buffer; + + break; + } + + case OPENAFS_SUBTAG_UNC: + { + + if( ulInputBufferLen < (ULONG)(FIELD_OFFSET( REPARSE_GUID_DATA_BUFFER, GenericReparseBuffer.DataBuffer) + + FIELD_OFFSET( AFSReparseTagInfo, UNCReferral.Buffer) + + pReparseInfo->UNCReferral.UNCTargetLength)) + { + + ntStatus = STATUS_IO_REPARSE_DATA_INVALID; + + break; + } + + uniTargetName.Length = pReparseInfo->UNCReferral.UNCTargetLength; + uniTargetName.MaximumLength = uniTargetName.Length; + + uniTargetName.Buffer = (WCHAR *)pReparseInfo->UNCReferral.Buffer; + + break; + } + + case OPENAFS_SUBTAG_MOUNTPOINT: + // + // Not yet handled + // + default: + { + + ntStatus = STATUS_IO_REPARSE_DATA_INVALID; + + break; + } + } + } + else { + // + // Handle Microsoft Reparse Tags + // - ntStatus = STATUS_IO_REPARSE_TAG_MISMATCH; + switch( pReparseGUIDBuffer->ReparseTag) + { + + case IO_REPARSE_TAG_MOUNT_POINT: + { + + pReparseBuffer = (REPARSE_DATA_BUFFER *)Irp->AssociatedIrp.SystemBuffer; + + uniTargetName.Length = pReparseBuffer->MountPointReparseBuffer.PrintNameLength; + uniTargetName.MaximumLength = uniTargetName.Length; + + uniTargetName.Buffer = (WCHAR *)((char *)pReparseBuffer->MountPointReparseBuffer.PathBuffer + + pReparseBuffer->MountPointReparseBuffer.PrintNameOffset); + + AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING, + AFS_TRACE_LEVEL_VERBOSE_2, + "AFSProcessUserFsRequest IO_REPARSE_TAG_MOUNT_POINT request %wZ\n", + &uniTargetName); + + ntStatus = STATUS_IO_REPARSE_DATA_INVALID; + + break; + } + + case IO_REPARSE_TAG_SYMLINK: + { + + pReparseBuffer = (REPARSE_DATA_BUFFER *)Irp->AssociatedIrp.SystemBuffer; + + uniTargetName.Length = pReparseBuffer->SymbolicLinkReparseBuffer.SubstituteNameLength; + uniTargetName.MaximumLength = uniTargetName.Length; + + uniTargetName.Buffer = (WCHAR *)((char *)pReparseBuffer->SymbolicLinkReparseBuffer.PathBuffer + + pReparseBuffer->SymbolicLinkReparseBuffer.SubstituteNameOffset); + + AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING, + AFS_TRACE_LEVEL_VERBOSE_2, + "AFSProcessUserFsRequest IO_REPARSE_TAG_SYMLINK request %wZ\n", + &uniTargetName); + break; + } + + default: + { + + ntStatus = STATUS_IO_REPARSE_DATA_INVALID; + + break; + } + } + } + + if( !NT_SUCCESS( ntStatus)) + { break; } - if( RtlCompareMemory( &pReparseBuffer->ReparseGuid, - &GUID_AFS_REPARSE_GUID, - sizeof( GUID)) != sizeof( GUID)) + // + // First thing is to locate/create our object information block + // for this entry + // + + AFSAcquireExcl( pCcb->DirectoryCB->ObjectInformation->VolumeCB->ObjectInfoTree.TreeLock, + TRUE); + + ullIndex = AFSCreateLowIndex( &pCcb->DirectoryCB->ObjectInformation->ParentFileId); + + ntStatus = AFSLocateHashEntry( pCcb->DirectoryCB->ObjectInformation->VolumeCB->ObjectInfoTree.TreeHead, + ullIndex, + (AFSBTreeEntry **)&pParentObjectInfo); + + if ( NT_SUCCESS( ntStatus) && + pParentObjectInfo) { - ntStatus = STATUS_REPARSE_ATTRIBUTE_CONFLICT; + lCount = AFSObjectInfoIncrement( pParentObjectInfo, + AFS_OBJECT_REFERENCE_DIRENTRY); - break; + AFSDbgLogMsg( AFS_SUBSYSTEM_OBJECT_REF_COUNTING, + AFS_TRACE_LEVEL_VERBOSE, + "AFSProcessUserFsRequest Increment count on object %p Cnt %d\n", + pParentObjectInfo, + lCount); } + AFSReleaseResource( pCcb->DirectoryCB->ObjectInformation->VolumeCB->ObjectInfoTree.TreeLock); + // - // For now deny access on this call + // Extract out the information to the call to the service // - ntStatus = STATUS_INVALID_PARAMETER; + ntStatus = AFSCreateSymlink( &pCcb->AuthGroup, + pParentObjectInfo, + &pCcb->DirectoryCB->NameInformation.FileName, + pCcb->DirectoryCB->ObjectInformation, + &uniTargetName); + + AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING, + AFS_TRACE_LEVEL_VERBOSE_2, + "AFSProcessUserFsRequest Processed FSCTL_SET_REPARSE_POINT request %wZ Type 0x%x Attrib 0x%x Status %08lX\n", + &pCcb->DirectoryCB->NameInformation.FileName, + pCcb->DirectoryCB->ObjectInformation->FileType, + pCcb->DirectoryCB->ObjectInformation->FileAttributes, + ntStatus); + + lCount = AFSObjectInfoDecrement( pParentObjectInfo, + AFS_OBJECT_REFERENCE_DIRENTRY); + + AFSDbgLogMsg( AFS_SUBSYSTEM_OBJECT_REF_COUNTING, + AFS_TRACE_LEVEL_VERBOSE, + "AFSProcessUserFsRequest Decrement count on object %p Cnt %d\n", + pParentObjectInfo, + lCount); break; } @@ -676,10 +848,12 @@ AFSProcessUserFsRequest( IN PIRP Irp) } // - // For now deny access on this call + // Claim success. The typical usage is setting delete on close + // as the next operation on the reparse point before closing + // the handle. // - ntStatus = STATUS_ACCESS_DENIED; + ntStatus = STATUS_SUCCESS; break; } @@ -727,6 +901,7 @@ AFSProcessShareFsCtrl( IN IRP *Irp, IN AFSCcb *Ccb) { + UNREFERENCED_PARAMETER(Fcb); NTSTATUS ntStatus = STATUS_SUCCESS; PIO_STACK_LOCATION pIrpSp = IoGetCurrentIrpStackLocation( Irp); ULONG ulOutputBufferLen = 0, ulInputBufferLen; @@ -774,30 +949,10 @@ AFSProcessShareFsCtrl( IN IRP *Irp, default: { - if( BooleanFlagOn( Ccb->DirectoryCB->Flags, AFS_DIR_ENTRY_SERVER_SERVICE)) - { - - //AFSPrint("AFSProcessShareFsCtrl (%08lX) For srvsvc input %08lX output %08lX\n", - // ulFsControlCode, - // ulInputBufferLen, - // ulOutputBufferLen); - } - else if( BooleanFlagOn( Ccb->DirectoryCB->Flags, AFS_DIR_ENTRY_WORKSTATION_SERVICE)) - { - - //AFSPrint("AFSProcessShareFsCtrl (%08lX) For wkssvc input %08lX output %08lX\n", - // ulFsControlCode, - // ulInputBufferLen, - // ulOutputBufferLen); - } - else - { - - //AFSPrint("AFSProcessShareFsCtrl (%08lX) For IPC$ input %08lX output %08lX\n", - // ulFsControlCode, - // ulInputBufferLen, - // ulOutputBufferLen); - } + AFSPrint( "AFSProcessShareFsCtrl (%08lX) For IPC$ input %08lX output %08lX\n", + ulFsControlCode, + ulInputBufferLen, + ulOutputBufferLen); break; }