/*
- * 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
* - 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
IN PIRP Irp)
{
+ UNREFERENCED_PARAMETER(LibDeviceObject);
NTSTATUS ntStatus = STATUS_SUCCESS;
IO_STACK_LOCATION *pIrpSp;
ntStatus);
}
- __except( AFSExceptionFilter( GetExceptionCode(), GetExceptionInformation()) )
+ __except( AFSExceptionFilter( __FUNCTION__, GetExceptionCode(), GetExceptionInformation()) )
{
AFSDbgLogMsg( 0,
0,
"EXCEPTION - AFSFSControl\n");
+
+ AFSDumpTraceFilesFnc();
}
return ntStatus;
// If a colon is not found, it means there is no cell
- if ( Cell->Buffer[ Cell->Length / sizeof( WCHAR)] == L':')
+ if ( Cell->Length < Target->Length - sizeof( WCHAR) &&
+ Cell->Buffer[ Cell->Length / sizeof( WCHAR)] == L':')
{
Cell->MaximumLength = Cell->Length;
pCcb = (AFSCcb *)pIrpSp->FileObject->FsContext2;
if( pFcb == NULL ||
+ pCcb == NULL ||
pCcb->DirectoryCB == NULL)
{
case FSCTL_OPLOCK_BREAK_NOTIFY:
case FSCTL_OPLOCK_BREAK_ACK_NO_2:
case FSCTL_REQUEST_FILTER_OPLOCK :
-
+ {
//
// Note that implementing this call will probably need us
// to call the server as well as adding code in read and
ntStatus = STATUS_NOT_IMPLEMENTED;
break;
+ }
case FSCTL_LOCK_VOLUME:
-
+ {
AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
AFS_TRACE_LEVEL_VERBOSE_2,
"AFSProcessUserFsRequest Processing FSCTL_LOCK_VOLUME request\n");
+ ntStatus = STATUS_NOT_IMPLEMENTED;
+
break;
+ }
case FSCTL_UNLOCK_VOLUME:
-
+ {
AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
AFS_TRACE_LEVEL_VERBOSE_2,
"AFSProcessUserFsRequest Processing FSCTL_UNLOCK_VOLUME request\n");
+ ntStatus = STATUS_NOT_IMPLEMENTED;
+
break;
+ }
case FSCTL_DISMOUNT_VOLUME:
-
+ {
AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
AFS_TRACE_LEVEL_VERBOSE_2,
"AFSProcessUserFsRequest Processing FSCTL_DISMOUNT_VOLUME request\n");
+ ntStatus = STATUS_NOT_IMPLEMENTED;
+
break;
+ }
case FSCTL_MARK_VOLUME_DIRTY:
-
+ {
AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
AFS_TRACE_LEVEL_VERBOSE_2,
"AFSProcessUserFsRequest Processing FSCTL_MARK_VOLUME_DIRTY request\n");
+ ntStatus = STATUS_NOT_IMPLEMENTED;
+
break;
+ }
case FSCTL_IS_VOLUME_DIRTY:
-
+ {
AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
AFS_TRACE_LEVEL_VERBOSE_2,
"AFSProcessUserFsRequest Processing FSCTL_IS_VOLUME_DIRTY request\n");
+ ntStatus = STATUS_NOT_IMPLEMENTED;
+
break;
+ }
case FSCTL_IS_VOLUME_MOUNTED:
-
+ {
AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
AFS_TRACE_LEVEL_VERBOSE_2,
"AFSProcessUserFsRequest Processing FSCTL_IS_VOLUME_MOUNTED request\n");
+ ntStatus = STATUS_NOT_IMPLEMENTED;
+
break;
+ }
case FSCTL_IS_PATHNAME_VALID:
-
+ {
AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
AFS_TRACE_LEVEL_VERBOSE_2,
"AFSProcessUserFsRequest Processing FSCTL_IS_PATHNAME_VALID request\n");
+ ntStatus = STATUS_SUCCESS;
+
break;
+ }
+
+#ifndef FSCTL_CSC_INTERNAL
+#define FSCTL_CSC_INTERNAL CTL_CODE(FILE_DEVICE_FILE_SYSTEM, 107, METHOD_NEITHER, FILE_ANY_ACCESS)
+#endif
+ case FSCTL_CSC_INTERNAL:
+ {
+ AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
+ AFS_TRACE_LEVEL_VERBOSE_2,
+ "AFSProcessUserFsRequest Processing FSCTL_CSC_INTERNAL request\n");
+
+ ntStatus = STATUS_INVALID_DEVICE_REQUEST;
+
+ break;
+ }
case FSCTL_GET_REPARSE_POINT:
{
AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
AFS_TRACE_LEVEL_VERBOSE_2,
- "AFSProcessUserFsRequest Processing FSCTL_GET_REPARSE_POINT request\n");
-
- if( ulOutputBufferLen < FIELD_OFFSET( REPARSE_GUID_DATA_BUFFER, GenericReparseBuffer.DataBuffer))
- {
-
- ntStatus = STATUS_BUFFER_TOO_SMALL;
-
- Irp->IoStatus.Information = FIELD_OFFSET( REPARSE_GUID_DATA_BUFFER, GenericReparseBuffer.DataBuffer);
-
- break;
- }
-
- ulRemainingLen -= FIELD_OFFSET( REPARSE_GUID_DATA_BUFFER, GenericReparseBuffer.DataBuffer);
+ "AFSProcessUserFsRequest Processing FSCTL_GET_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
break;
}
+ if( ulOutputBufferLen < FIELD_OFFSET( REPARSE_GUID_DATA_BUFFER, GenericReparseBuffer.DataBuffer))
+ {
+
+ ntStatus = STATUS_BUFFER_TOO_SMALL;
+
+ Irp->IoStatus.Information = FIELD_OFFSET( REPARSE_GUID_DATA_BUFFER, GenericReparseBuffer.DataBuffer);
+
+ break;
+ }
+
+ ulRemainingLen -= FIELD_OFFSET( REPARSE_GUID_DATA_BUFFER, GenericReparseBuffer.DataBuffer);
+
//
// Populate the data in the reparse buffer
//
pCcb->DirectoryCB->ObjectInformation->FileId.Vnode,
pCcb->DirectoryCB->ObjectInformation->FileId.Unique);
- ntStatus = AFSVerifyEntry( &pFcb->AuthGroup,
+ ntStatus = AFSVerifyEntry( &pCcb->AuthGroup,
pCcb->DirectoryCB);
if( !NT_SUCCESS( ntStatus))
if( pCcb->DirectoryCB->NameInformation.TargetName.Length == 0)
{
- ntStatus = STATUS_ACCESS_DENIED;
+ ntStatus = STATUS_REPARSE_POINT_NOT_RESOLVED;
break;
}
if( pCcb->DirectoryCB->NameInformation.TargetName.Length == 0)
{
- ntStatus = STATUS_ACCESS_DENIED;
+ ntStatus = STATUS_REPARSE_POINT_NOT_RESOLVED;
break;
}
if( pCcb->DirectoryCB->NameInformation.TargetName.Length == 0)
{
- ntStatus = STATUS_ACCESS_DENIED;
+ ntStatus = STATUS_REPARSE_POINT_NOT_RESOLVED;
break;
}
ulRemainingLen -= pReparseBuffer->ReparseDataLength;
- pReparseBuffer->ReparseTag = IO_REPARSE_TAG_OPENAFS_DFS;
+ pReparseBuffer->ReparseTag = IO_REPARSE_TAG_SURROGATE|IO_REPARSE_TAG_OPENAFS_DFS;
RtlCopyMemory( &pReparseBuffer->ReparseGuid,
&GUID_AFS_REPARSE_GUID,
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,
- "AFSProcessUserFsRequest Processing FSCTL_SET_REPARSE_POINT request\n");
+ 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);
if( ulInputBufferLen < FIELD_OFFSET( REPARSE_GUID_DATA_BUFFER, GenericReparseBuffer.DataBuffer))
{
- ntStatus = STATUS_INVALID_PARAMETER;
+ ntStatus = STATUS_IO_REPARSE_DATA_INVALID;
break;
}
- //
- // Check if we have the reparse entry set on the entry
- //
+ if( (pReparseGUIDBuffer->ReparseTag & 0x0000FFFF) == IO_REPARSE_TAG_OPENAFS_DFS)
+ {
- if( !BooleanFlagOn( pCcb->DirectoryCB->ObjectInformation->FileAttributes, FILE_ATTRIBUTE_REPARSE_POINT))
+ if( RtlCompareMemory( &pReparseGUIDBuffer->ReparseGuid,
+ &GUID_AFS_REPARSE_GUID,
+ sizeof( GUID)) != sizeof( GUID))
+ {
+
+ ntStatus = STATUS_REPARSE_ATTRIBUTE_CONFLICT;
+
+ 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_NOT_A_REPARSE_POINT;
+ switch( pReparseGUIDBuffer->ReparseTag)
+ {
- break;
+ 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( pReparseBuffer->ReparseTag != IO_REPARSE_TAG_OPENAFS_DFS)
+ if( !NT_SUCCESS( ntStatus))
{
- ntStatus = STATUS_IO_REPARSE_TAG_MISMATCH;
-
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 = 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;
}
AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
AFS_TRACE_LEVEL_VERBOSE_2,
- "AFSProcessUserFsRequest Processing FSCTL_DELETE_REPARSE_POINT request\n");
-
- if( ulInputBufferLen < FIELD_OFFSET( REPARSE_GUID_DATA_BUFFER, GenericReparseBuffer.DataBuffer))
- {
-
- ntStatus = STATUS_INVALID_PARAMETER;
-
- break;
- }
+ "AFSProcessUserFsRequest Processing FSCTL_DELETE_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
break;
}
- if( pReparseBuffer->ReparseTag != IO_REPARSE_TAG_OPENAFS_DFS)
+ if( ulInputBufferLen < FIELD_OFFSET( REPARSE_GUID_DATA_BUFFER, GenericReparseBuffer.DataBuffer))
+ {
+
+ ntStatus = STATUS_INVALID_PARAMETER;
+
+ break;
+ }
+
+ if( (pReparseBuffer->ReparseTag & 0x0000FFFF) != IO_REPARSE_TAG_OPENAFS_DFS)
{
ntStatus = STATUS_IO_REPARSE_TAG_MISMATCH;
}
//
- // 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_SUCCESS;
+
+ break;
+ }
+
+#ifndef FSCTL_SET_PURGE_FAILURE_MODE
+#define FSCTL_SET_PURGE_FAILURE_MODE CTL_CODE(FILE_DEVICE_FILE_SYSTEM, 156, METHOD_BUFFERED, FILE_ANY_ACCESS)
+#endif
+
+ case FSCTL_SET_PURGE_FAILURE_MODE:
+ {
+
+ //
+ // For the time being just succeed this call
//
- ntStatus = STATUS_ACCESS_DENIED;
+ ntStatus = STATUS_SUCCESS;
break;
}
default :
+ {
AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
AFS_TRACE_LEVEL_VERBOSE_2,
"AFSProcessUserFsRequest Processing default (%08lX) request\n", ulFsControlCode);
- ntStatus = STATUS_INVALID_PARAMETER;
+ ntStatus = STATUS_INVALID_DEVICE_REQUEST;
break;
+ }
}
try_exit:
IN AFSCcb *Ccb)
{
+ UNREFERENCED_PARAMETER(Fcb);
NTSTATUS ntStatus = STATUS_SUCCESS;
PIO_STACK_LOCATION pIrpSp = IoGetCurrentIrpStackLocation( Irp);
ULONG ulOutputBufferLen = 0, ulInputBufferLen;
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;
}