BOOLEAN AFSIs64BitProcess( IN ULONGLONG ProcessId) { NTSTATUS ntStatus = STATUS_SUCCESS; BOOLEAN bIs64Bit = FALSE; AFSProcessCB *pProcessCB = NULL; AFSDeviceExt *pDeviceExt = (AFSDeviceExt *)AFSDeviceObject->DeviceExtension; __Enter { AFSDbgTrace(( AFS_SUBSYSTEM_LOCK_PROCESSING, AFS_TRACE_LEVEL_VERBOSE, "AFSIs64BitProcess Acquiring Control ProcessTree.TreeLock lock %p SHARED %08lX\n", pDeviceExt->Specific.Control.ProcessTree.TreeLock, PsGetCurrentThread())); AFSAcquireShared( pDeviceExt->Specific.Control.ProcessTree.TreeLock, TRUE); ntStatus = AFSLocateHashEntry( pDeviceExt->Specific.Control.ProcessTree.TreeHead, (ULONGLONG)ProcessId, (AFSBTreeEntry **)&pProcessCB); if( pProcessCB != NULL) { bIs64Bit = BooleanFlagOn( pProcessCB->Flags, AFS_PROCESS_FLAG_IS_64BIT); } AFSReleaseResource( pDeviceExt->Specific.Control.ProcessTree.TreeLock); } return bIs64Bit; }
NTSTATUS AFSQueryVolumeInfo( IN PDEVICE_OBJECT LibDeviceObject, IN PIRP Irp) { NTSTATUS ntStatus = STATUS_SUCCESS; AFSDeviceExt *pDeviceExt = (AFSDeviceExt *)AFSRDRDeviceObject->DeviceExtension; IO_STACK_LOCATION *pIrpSp; FS_INFORMATION_CLASS FsInformationClass; void *pBuffer = NULL; ULONG ulLength = 0; BOOLEAN bReleaseResource = FALSE; PFILE_OBJECT pFileObject = NULL; AFSFcb *pFcb = NULL; AFSObjectInfoCB *pObjectInfo = NULL; AFSVolumeCB *pVolumeCB = NULL; pIrpSp = IoGetCurrentIrpStackLocation( Irp); __try { pFileObject = pIrpSp->FileObject; if( pFileObject == NULL) { AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING, AFS_TRACE_LEVEL_ERROR, "AFSQueryVolumeInfo Failing request with NULL FileObject\n"); try_return( ntStatus = STATUS_INVALID_DEVICE_REQUEST); } pFcb = (AFSFcb *)pFileObject->FsContext; if( pFcb == NULL) { AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING, AFS_TRACE_LEVEL_ERROR, "AFSQueryVolumeInfo Failing request with NULL Fcb\n"); try_return( ntStatus = STATUS_INVALID_DEVICE_REQUEST); } pObjectInfo = pFcb->ObjectInformation; if( pObjectInfo == NULL) { AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING, AFS_TRACE_LEVEL_ERROR, "AFSQueryVolumeInfo Failing request with NULL ObjectInformation\n"); try_return( ntStatus = STATUS_INVALID_DEVICE_REQUEST); } pVolumeCB = pObjectInfo->VolumeCB; ulLength = pIrpSp->Parameters.QueryVolume.Length; FsInformationClass = pIrpSp->Parameters.QueryVolume.FsInformationClass; pBuffer = Irp->AssociatedIrp.SystemBuffer; AFSAcquireShared( pVolumeCB->VolumeLock, TRUE); bReleaseResource = TRUE; // // Don't allow requests against IOCtl nodes // if( pFcb->Header.NodeTypeCode == AFS_IOCTL_FCB) { AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING, AFS_TRACE_LEVEL_ERROR, "AFSQueryVolumeInfo Failing request against PIOCtl Fcb\n"); try_return( ntStatus = STATUS_INVALID_DEVICE_REQUEST); } else if( pFcb->Header.NodeTypeCode == AFS_SPECIAL_SHARE_FCB) { AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING, AFS_TRACE_LEVEL_ERROR, "AFSQueryVolumeInfo Failing request against SpecialShare Fcb\n"); try_return( ntStatus = STATUS_INVALID_DEVICE_REQUEST); } else if( pFcb->Header.NodeTypeCode == AFS_INVALID_FCB) { AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING, AFS_TRACE_LEVEL_ERROR, "AFSQueryVolumeInfo Failing request against SpecialShare Fcb\n"); try_return( ntStatus = STATUS_INVALID_DEVICE_REQUEST); } // // Process the request // switch( FsInformationClass) { case FileFsVolumeInformation: { ntStatus = AFSQueryFsVolumeInfo( &pVolumeCB->VolumeInformation, (PFILE_FS_VOLUME_INFORMATION)pBuffer, &ulLength); break; } case FileFsSizeInformation: { ntStatus = AFSQueryFsSizeInfo( &pVolumeCB->VolumeInformation, (PFILE_FS_SIZE_INFORMATION)pBuffer, &ulLength); break; } case FileFsDeviceInformation: { ntStatus = AFSQueryFsDeviceInfo( &pVolumeCB->VolumeInformation, (PFILE_FS_DEVICE_INFORMATION)pBuffer, &ulLength); break; } case FileFsAttributeInformation: { ntStatus = AFSQueryFsAttributeInfo( &pVolumeCB->VolumeInformation, (PFILE_FS_ATTRIBUTE_INFORMATION)pBuffer, &ulLength); break; } case FileFsFullSizeInformation: { ntStatus = AFSQueryFsFullSizeInfo( &pVolumeCB->VolumeInformation, (PFILE_FS_FULL_SIZE_INFORMATION)pBuffer, &ulLength); break; } default: AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING, AFS_TRACE_LEVEL_WARNING, "AFSQueryVolumeInfo Invalid class %d\n", FsInformationClass); ntStatus = STATUS_INVALID_PARAMETER; break; } try_exit: // // Setup the Irp's information field to what we actually copied in. // Irp->IoStatus.Information = pIrpSp->Parameters.QueryVolume.Length - ulLength; if( bReleaseResource) { AFSReleaseResource( pVolumeCB->VolumeLock); } AFSCompleteRequest( Irp, ntStatus); } __except( AFSExceptionFilter( __FUNCTION__, GetExceptionCode(), GetExceptionInformation()) ) { AFSDbgLogMsg( 0, 0, "EXCEPTION - AFSQueryVolumeInfo FO %08lX InfoClass %d FCB %08lX ObjectInfo %08lX VolCB %08lX\n", pFileObject, FsInformationClass, pFcb, pObjectInfo, pVolumeCB); AFSDumpTraceFilesFnc(); } return ntStatus; }
NTSTATUS AFSFlushBuffers( IN PDEVICE_OBJECT LibDeviceObject, IN PIRP Irp) { UNREFERENCED_PARAMETER(LibDeviceObject); AFSDeviceExt *pRDRDevExt = (AFSDeviceExt *) AFSRDRDeviceObject->DeviceExtension; NTSTATUS ntStatus = STATUS_SUCCESS; IO_STACK_LOCATION *pIrpSp = IoGetCurrentIrpStackLocation( Irp); PFILE_OBJECT pFileObject = pIrpSp->FileObject; AFSFcb *pFcb = (AFSFcb *)pFileObject->FsContext; AFSCcb *pCcb = (AFSCcb *)pFileObject->FsContext2; IO_STATUS_BLOCK iosb = {0}; BOOLEAN bReleaseSectionObject = FALSE; pIrpSp = IoGetCurrentIrpStackLocation( Irp); __Enter { if( pFcb == NULL) { AFSDbgTrace(( AFS_SUBSYSTEM_FILE_PROCESSING, AFS_TRACE_LEVEL_ERROR, "AFSFlushBuffers Attempted access (%p) when pFcb == NULL\n", Irp)); try_return( ntStatus = STATUS_INVALID_DEVICE_REQUEST); } if( pFcb->Header.NodeTypeCode == AFS_ROOT_FCB || pFcb->Header.NodeTypeCode == AFS_ROOT_ALL ) { // // Once we support ADS's on directories we need to perform a flush ehre // try_return( ntStatus = STATUS_SUCCESS); } else if (pFcb->Header.NodeTypeCode != AFS_FILE_FCB) { // // Nothing to flush Everything but files are write through // try_return( ntStatus = STATUS_INVALID_PARAMETER); } AFSDbgTrace(( AFS_SUBSYSTEM_LOCK_PROCESSING|AFS_SUBSYSTEM_SECTION_OBJECT, AFS_TRACE_LEVEL_VERBOSE, "AFSFlushBuffers Acquiring Fcb SectionObject lock %p SHARED %08lX\n", &pFcb->NPFcb->SectionObjectResource, PsGetCurrentThread())); AFSAcquireShared( &pFcb->NPFcb->SectionObjectResource, TRUE); bReleaseSectionObject = TRUE; // // The flush consists of two parts. We firstly flush our // cache (if we have one), then we tell the service to write // to the remote server // __try { CcFlushCache( &pFcb->NPFcb->SectionObjectPointers, NULL, 0, &iosb); if (!NT_SUCCESS( iosb.Status )) { AFSDbgTrace(( AFS_SUBSYSTEM_IO_PROCESSING, AFS_TRACE_LEVEL_ERROR, "AFSFlushBuffers CcFlushCache [1] failure FID %08lX-%08lX-%08lX-%08lX Status 0x%08lX Bytes 0x%08lX\n", pFcb->ObjectInformation->FileId.Cell, pFcb->ObjectInformation->FileId.Volume, pFcb->ObjectInformation->FileId.Vnode, pFcb->ObjectInformation->FileId.Unique, iosb.Status, iosb.Information)); try_return( ntStatus = iosb.Status ); } } __except( AFSExceptionFilter( __FUNCTION__, GetExceptionCode(), GetExceptionInformation())) { try_return( ntStatus = GetExceptionCode()); } if( !BooleanFlagOn( pRDRDevExt->DeviceFlags, AFS_DEVICE_FLAG_DIRECT_SERVICE_IO)) { AFSDbgTrace(( AFS_SUBSYSTEM_LOCK_PROCESSING|AFS_SUBSYSTEM_SECTION_OBJECT, AFS_TRACE_LEVEL_VERBOSE, "AFSFlushBuffers Releasing Fcb SectionObject lock %p SHARED %08lX\n", &pFcb->NPFcb->SectionObjectResource, PsGetCurrentThread())); AFSReleaseResource( &pFcb->NPFcb->SectionObjectResource); bReleaseSectionObject = FALSE; // // Now, flush to the server - if there is stuff to do // ntStatus = AFSFlushExtents( pFcb, &pCcb->AuthGroup); if( !NT_SUCCESS( ntStatus)) { AFSReleaseExtentsWithFlush( pFcb, &pCcb->AuthGroup, TRUE); ntStatus = STATUS_SUCCESS; } } try_exit: if ( bReleaseSectionObject) { AFSDbgTrace(( AFS_SUBSYSTEM_LOCK_PROCESSING|AFS_SUBSYSTEM_SECTION_OBJECT, AFS_TRACE_LEVEL_VERBOSE, "AFSFlushBuffers Releasing Fcb SectionObject lock %p SHARED %08lX\n", &pFcb->NPFcb->SectionObjectResource, PsGetCurrentThread())); AFSReleaseResource( &pFcb->NPFcb->SectionObjectResource); } AFSCompleteRequest( Irp, ntStatus); } return ntStatus; }
void AFSDumpTraceFiles() { NTSTATUS ntStatus = STATUS_SUCCESS; HANDLE hDirectory = NULL; OBJECT_ATTRIBUTES stObjectAttribs; IO_STATUS_BLOCK stIoStatus; LARGE_INTEGER liTime, liLocalTime; TIME_FIELDS timeFields; ULONG ulBytesWritten = 0; HANDLE hDumpFile = NULL; ULONG ulBytesProcessed, ulCopyLength; LARGE_INTEGER liOffset; ULONG ulDumpLength = 0; BOOLEAN bSetEvent = FALSE; __Enter { AFSAcquireShared( &AFSDbgLogLock, TRUE); ulDumpLength = AFSDbgBufferLength - AFSDbgLogRemainingLength; AFSReleaseResource( &AFSDbgLogLock); if( AFSDumpFileLocation.Length == 0 || AFSDumpFileLocation.Buffer == NULL || AFSDbgBufferLength == 0 || ulDumpLength == 0 || AFSDumpFileName.MaximumLength == 0 || AFSDumpFileName.Buffer == NULL || AFSDumpBuffer == NULL) { try_return( ntStatus); } // // Go open the cache file // InitializeObjectAttributes( &stObjectAttribs, &AFSDumpFileLocation, OBJ_KERNEL_HANDLE | OBJ_CASE_INSENSITIVE, NULL, NULL); ntStatus = ZwCreateFile( &hDirectory, GENERIC_READ | GENERIC_WRITE, &stObjectAttribs, &stIoStatus, NULL, 0, FILE_SHARE_READ | FILE_SHARE_WRITE, FILE_OPEN, FILE_DIRECTORY_FILE | FILE_SYNCHRONOUS_IO_NONALERT, NULL, 0); if( !NT_SUCCESS( ntStatus)) { try_return( ntStatus); } ntStatus = KeWaitForSingleObject( &AFSDumpFileEvent, Executive, KernelMode, FALSE, NULL); if( !NT_SUCCESS( ntStatus)) { try_return( ntStatus); } bSetEvent = TRUE; AFSDumpFileName.Length = 0; RtlZeroMemory( AFSDumpFileName.Buffer, AFSDumpFileName.MaximumLength); KeQuerySystemTime( &liTime); ExSystemTimeToLocalTime( &liTime, &liLocalTime); RtlTimeToTimeFields( &liLocalTime, &timeFields); ntStatus = RtlStringCchPrintfW( AFSDumpFileName.Buffer, AFSDumpFileName.MaximumLength/sizeof( WCHAR), L"AFSDumpFile %d.%d.%d %d.%d.%d.log", timeFields.Month, timeFields.Day, timeFields.Year, timeFields.Hour, timeFields.Minute, timeFields.Second); if( !NT_SUCCESS( ntStatus)) { try_return( ntStatus); } RtlStringCbLengthW( AFSDumpFileName.Buffer, AFSDumpFileName.MaximumLength, (size_t *)&ulBytesWritten); AFSDumpFileName.Length = (USHORT)ulBytesWritten; InitializeObjectAttributes( &stObjectAttribs, &AFSDumpFileName, OBJ_KERNEL_HANDLE | OBJ_CASE_INSENSITIVE, hDirectory, NULL); ntStatus = ZwCreateFile( &hDumpFile, GENERIC_READ | GENERIC_WRITE, &stObjectAttribs, &stIoStatus, NULL, 0, FILE_SHARE_READ | FILE_SHARE_WRITE, FILE_CREATE, FILE_SYNCHRONOUS_IO_NONALERT, NULL, 0); if( !NT_SUCCESS( ntStatus)) { try_return( ntStatus); } // // Write out the trace buffer // liOffset.QuadPart = 0; ulBytesProcessed = 0; while( ulBytesProcessed < ulDumpLength) { ulCopyLength = AFSDumpBufferLength; if( ulCopyLength > ulDumpLength - ulBytesProcessed) { ulCopyLength = ulDumpLength - ulBytesProcessed; } RtlCopyMemory( AFSDumpBuffer, (void *)((char *)AFSDbgBuffer + ulBytesProcessed), ulCopyLength); ntStatus = ZwWriteFile( hDumpFile, NULL, NULL, NULL, &stIoStatus, AFSDumpBuffer, ulCopyLength, &liOffset, NULL); if( !NT_SUCCESS( ntStatus)) { break; } liOffset.QuadPart += ulCopyLength; ulBytesProcessed += ulCopyLength; } try_exit: if( hDumpFile != NULL) { ZwClose( hDumpFile); } if( hDirectory != NULL) { ZwClose( hDirectory); } if( bSetEvent) { KeSetEvent( &AFSDumpFileEvent, 0, FALSE); } } return; }
NTSTATUS AFSGetTraceBuffer( IN ULONG TraceBufferLength, OUT void *TraceBuffer, OUT ULONG_PTR *CopiedLength) { NTSTATUS ntStatus = STATUS_SUCCESS; ULONG ulCopyLength = 0; char *pCurrentLocation = NULL; __Enter { AFSAcquireShared( &AFSDbgLogLock, TRUE); if( TraceBufferLength < AFSDbgBufferLength) { try_return( ntStatus = STATUS_INVALID_PARAMETER); } // // If we have wrapped then copy in the remaining portion // pCurrentLocation = (char *)TraceBuffer; *CopiedLength = 0; if( BooleanFlagOn( AFSDbgLogFlags, AFS_DBG_LOG_WRAPPED)) { ulCopyLength = AFSDbgLogRemainingLength; RtlCopyMemory( pCurrentLocation, AFSDbgCurrentBuffer, ulCopyLength); pCurrentLocation[ 0] = '0'; // The buffer is NULL terminated ... pCurrentLocation += ulCopyLength; *CopiedLength = ulCopyLength; } ulCopyLength = AFSDbgBufferLength - AFSDbgLogRemainingLength; if( ulCopyLength > 0) { RtlCopyMemory( pCurrentLocation, AFSDbgBuffer, ulCopyLength); *CopiedLength += ulCopyLength; } try_exit: AFSReleaseResource( &AFSDbgLogLock); } return ntStatus; }
NTSTATUS AFSProcessUserFsRequest( IN PIRP Irp) { NTSTATUS ntStatus = STATUS_SUCCESS; ULONG ulFsControlCode; AFSFcb *pFcb = NULL; PIO_STACK_LOCATION pIrpSp = IoGetCurrentIrpStackLocation( Irp ); AFSCcb *pCcb = NULL; ULONG ulOutputBufferLen, ulInputBufferLen; __Enter { ulFsControlCode = pIrpSp->Parameters.FileSystemControl.FsControlCode; pFcb = (AFSFcb *)pIrpSp->FileObject->FsContext; pCcb = (AFSCcb *)pIrpSp->FileObject->FsContext2; if( pFcb == NULL || pCcb == NULL || pCcb->DirectoryCB == NULL) { AFSDbgTrace(( AFS_SUBSYSTEM_FILE_PROCESSING, AFS_TRACE_LEVEL_VERBOSE_2, "AFSProcessUserFsRequest Invalid Fcb\n")); try_return( ntStatus = STATUS_INVALID_DEVICE_REQUEST); } if( pFcb->Header.NodeTypeCode == AFS_SPECIAL_SHARE_FCB) { ntStatus = AFSProcessShareFsCtrl( Irp, pFcb, pCcb); try_return( ntStatus); } ulOutputBufferLen = pIrpSp->Parameters.FileSystemControl.OutputBufferLength; ulInputBufferLen = pIrpSp->Parameters.FileSystemControl.InputBufferLength; // // Process the request // switch( ulFsControlCode ) { case FSCTL_REQUEST_OPLOCK_LEVEL_1: case FSCTL_REQUEST_OPLOCK_LEVEL_2: case FSCTL_REQUEST_BATCH_OPLOCK: case FSCTL_OPLOCK_BREAK_ACKNOWLEDGE: case FSCTL_OPBATCH_ACK_CLOSE_PENDING: 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 // write and caching. Also that it is unlikely that // anyone will ever call us at this point - RDR doesn't // allow it // ntStatus = STATUS_NOT_IMPLEMENTED; break; } case FSCTL_LOCK_VOLUME: { AFSDbgTrace(( 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: { AFSDbgTrace(( 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: { AFSDbgTrace(( 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: { AFSDbgTrace(( 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: { AFSDbgTrace(( 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: { AFSDbgTrace(( 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: { AFSDbgTrace(( 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: { AFSDbgTrace(( 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: { REPARSE_GUID_DATA_BUFFER *pReparseBuffer = (REPARSE_GUID_DATA_BUFFER *)Irp->AssociatedIrp.SystemBuffer; REPARSE_DATA_BUFFER *pMSFTReparseBuffer = (REPARSE_DATA_BUFFER *)Irp->AssociatedIrp.SystemBuffer; ULONG ulRemainingLen = ulOutputBufferLen; AFSReparseTagInfo *pReparseInfo = NULL; BOOLEAN bRelative = FALSE; BOOLEAN bDriveLetter = FALSE; WCHAR * PathBuffer = NULL; AFSDbgTrace(( AFS_SUBSYSTEM_FILE_PROCESSING, AFS_TRACE_LEVEL_VERBOSE_2, "AFSProcessUserFsRequest Processing FSCTL_GET_REPARSE_POINT request %wZ Type 0x%x Attrib 0x%x\n", &pCcb->DirectoryCB->NameInformation.FileName, pFcb->ObjectInformation->FileType, pFcb->ObjectInformation->FileAttributes)); // // Check if we have the reparse entry set on the entry // if( !BooleanFlagOn( pFcb->ObjectInformation->FileAttributes, FILE_ATTRIBUTE_REPARSE_POINT)) { ntStatus = STATUS_NOT_A_REPARSE_POINT; break; } switch ( pFcb->ObjectInformation->FileType) { case AFS_FILE_TYPE_MOUNTPOINT: 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); break; default: if( ulOutputBufferLen < FIELD_OFFSET( REPARSE_DATA_BUFFER, GenericReparseBuffer.DataBuffer)) { ntStatus = STATUS_BUFFER_TOO_SMALL; Irp->IoStatus.Information = FIELD_OFFSET( REPARSE_DATA_BUFFER, GenericReparseBuffer.DataBuffer); break; } ulRemainingLen -= FIELD_OFFSET( REPARSE_DATA_BUFFER, GenericReparseBuffer.DataBuffer); break; } // // Populate the data in the reparse buffer // pReparseBuffer->ReparseDataLength = 0; AFSAcquireExcl( &pCcb->DirectoryCB->NonPaged->Lock, TRUE); if( pCcb->DirectoryCB->NameInformation.TargetName.Length == 0) { // // We'll reset the DV to ensure we validate the metadata content // pFcb->ObjectInformation->DataVersion.QuadPart = (ULONGLONG)-1; SetFlag( pFcb->ObjectInformation->Flags, AFS_OBJECT_FLAGS_VERIFY); AFSDbgTrace(( AFS_SUBSYSTEM_FILE_PROCESSING, AFS_TRACE_LEVEL_VERBOSE, "AFSProcessUserFsRequest Verifying symlink %wZ FID %08lX-%08lX-%08lX-%08lX\n", &pCcb->DirectoryCB->NameInformation.FileName, pFcb->ObjectInformation->FileId.Cell, pFcb->ObjectInformation->FileId.Volume, pFcb->ObjectInformation->FileId.Vnode, pFcb->ObjectInformation->FileId.Unique)); ntStatus = AFSVerifyEntry( &pCcb->AuthGroup, pCcb->DirectoryCB, FALSE); if( !NT_SUCCESS( ntStatus)) { AFSDbgTrace(( AFS_SUBSYSTEM_FILE_PROCESSING, AFS_TRACE_LEVEL_ERROR, "AFSProcessUserFsRequest Failed to verify symlink %wZ FID %08lX-%08lX-%08lX-%08lX Status %08lX\n", &pCcb->DirectoryCB->NameInformation.FileName, pFcb->ObjectInformation->FileId.Cell, pFcb->ObjectInformation->FileId.Volume, pFcb->ObjectInformation->FileId.Vnode, pFcb->ObjectInformation->FileId.Unique, ntStatus)); AFSReleaseResource( &pCcb->DirectoryCB->NonPaged->Lock); break; } } pReparseInfo = (AFSReparseTagInfo *)&pReparseBuffer->GenericReparseBuffer.DataBuffer[ 0]; switch( pFcb->ObjectInformation->FileType) { case AFS_FILE_TYPE_SYMLINK: { if( pCcb->DirectoryCB->NameInformation.TargetName.Length == 0) { ntStatus = STATUS_REPARSE_POINT_NOT_RESOLVED; break; } bRelative = AFSIsRelativeName( &pCcb->DirectoryCB->NameInformation.TargetName); if ( bRelative) { if( ulRemainingLen < (ULONG) FIELD_OFFSET( REPARSE_DATA_BUFFER, SymbolicLinkReparseBuffer.PathBuffer) + pCcb->DirectoryCB->NameInformation.TargetName.Length) { ntStatus = STATUS_BUFFER_TOO_SMALL; Irp->IoStatus.Information = FIELD_OFFSET( REPARSE_DATA_BUFFER, SymbolicLinkReparseBuffer.PathBuffer) + pCcb->DirectoryCB->NameInformation.TargetName.Length; break; } pMSFTReparseBuffer->SymbolicLinkReparseBuffer.Flags = SYMLINK_FLAG_RELATIVE; pMSFTReparseBuffer->SymbolicLinkReparseBuffer.SubstituteNameLength = pCcb->DirectoryCB->NameInformation.TargetName.Length; pMSFTReparseBuffer->SymbolicLinkReparseBuffer.PrintNameLength = pCcb->DirectoryCB->NameInformation.TargetName.Length; pMSFTReparseBuffer->SymbolicLinkReparseBuffer.SubstituteNameOffset = 0; pMSFTReparseBuffer->SymbolicLinkReparseBuffer.PrintNameOffset = 0; PathBuffer = pMSFTReparseBuffer->SymbolicLinkReparseBuffer.PathBuffer; RtlCopyMemory( PathBuffer, pCcb->DirectoryCB->NameInformation.TargetName.Buffer, pCcb->DirectoryCB->NameInformation.TargetName.Length); pReparseBuffer->ReparseDataLength = FIELD_OFFSET( REPARSE_DATA_BUFFER, SymbolicLinkReparseBuffer.PathBuffer) - FIELD_OFFSET( REPARSE_DATA_BUFFER, GenericReparseBuffer.DataBuffer) + pMSFTReparseBuffer->SymbolicLinkReparseBuffer.SubstituteNameLength; } else { if( ulRemainingLen < (ULONG) FIELD_OFFSET( REPARSE_DATA_BUFFER, SymbolicLinkReparseBuffer.PathBuffer) + /* Display Name */ pCcb->DirectoryCB->NameInformation.TargetName.Length + 1 * sizeof( WCHAR) + /* Substitute Name */ pCcb->DirectoryCB->NameInformation.TargetName.Length + 7 * sizeof( WCHAR)) { ntStatus = STATUS_BUFFER_TOO_SMALL; Irp->IoStatus.Information = FIELD_OFFSET( REPARSE_DATA_BUFFER, SymbolicLinkReparseBuffer.PathBuffer) + pCcb->DirectoryCB->NameInformation.TargetName.Length + 1 * sizeof( WCHAR) + pCcb->DirectoryCB->NameInformation.TargetName.Length + 7 * sizeof( WCHAR); break; } pMSFTReparseBuffer->SymbolicLinkReparseBuffer.Flags = 0; pMSFTReparseBuffer->SymbolicLinkReparseBuffer.SubstituteNameLength = pCcb->DirectoryCB->NameInformation.TargetName.Length + 7 * sizeof( WCHAR); pMSFTReparseBuffer->SymbolicLinkReparseBuffer.PrintNameLength = pCcb->DirectoryCB->NameInformation.TargetName.Length + 1 * sizeof( WCHAR); pMSFTReparseBuffer->SymbolicLinkReparseBuffer.SubstituteNameOffset = pMSFTReparseBuffer->SymbolicLinkReparseBuffer.PrintNameLength; pMSFTReparseBuffer->SymbolicLinkReparseBuffer.PrintNameOffset = 0; PathBuffer = pMSFTReparseBuffer->SymbolicLinkReparseBuffer.PathBuffer; /* Display Name */ *PathBuffer++ = L'\\'; RtlCopyMemory( PathBuffer, pCcb->DirectoryCB->NameInformation.TargetName.Buffer, pCcb->DirectoryCB->NameInformation.TargetName.Length); PathBuffer += pCcb->DirectoryCB->NameInformation.TargetName.Length / sizeof( WCHAR); /* Substitute Name */ *PathBuffer++ = L'\\'; *PathBuffer++ = L'?'; *PathBuffer++ = L'?'; *PathBuffer++ = L'\\'; *PathBuffer++ = L'U'; *PathBuffer++ = L'N'; *PathBuffer++ = L'C'; RtlCopyMemory( PathBuffer, pCcb->DirectoryCB->NameInformation.TargetName.Buffer, pCcb->DirectoryCB->NameInformation.TargetName.Length); pReparseBuffer->ReparseDataLength = FIELD_OFFSET( REPARSE_DATA_BUFFER, SymbolicLinkReparseBuffer.PathBuffer) - FIELD_OFFSET( REPARSE_DATA_BUFFER, GenericReparseBuffer.DataBuffer) + pMSFTReparseBuffer->SymbolicLinkReparseBuffer.PrintNameLength + pMSFTReparseBuffer->SymbolicLinkReparseBuffer.SubstituteNameLength; } break; } case AFS_FILE_TYPE_MOUNTPOINT: { UNICODE_STRING Cell, Volume; USHORT Type; if( pCcb->DirectoryCB->NameInformation.TargetName.Length == 0) { ntStatus = STATUS_REPARSE_POINT_NOT_RESOLVED; break; } if ( !AFSParseMountPointTarget( &pCcb->DirectoryCB->NameInformation.TargetName, &Type, &Volume, &Cell)) { ntStatus = STATUS_INVALID_PARAMETER; break; } if( ulRemainingLen < (ULONG) FIELD_OFFSET( AFSReparseTagInfo, AFSMountPoint.Buffer) + Volume.Length + Cell.Length) { ntStatus = STATUS_BUFFER_TOO_SMALL; Irp->IoStatus.Information = FIELD_OFFSET( REPARSE_GUID_DATA_BUFFER, GenericReparseBuffer.DataBuffer) + FIELD_OFFSET( AFSReparseTagInfo, AFSMountPoint.Buffer) + Volume.Length + Cell.Length; break; } pReparseInfo->SubTag = OPENAFS_SUBTAG_MOUNTPOINT; pReparseInfo->AFSMountPoint.Type = Type; pReparseInfo->AFSMountPoint.MountPointCellLength = Cell.Length; pReparseInfo->AFSMountPoint.MountPointVolumeLength = Volume.Length; RtlCopyMemory( pReparseInfo->AFSMountPoint.Buffer, Cell.Buffer, Cell.Length); RtlCopyMemory( &pReparseInfo->AFSMountPoint.Buffer[ Cell.Length / sizeof( WCHAR)], Volume.Buffer, Volume.Length); pReparseBuffer->ReparseDataLength = (FIELD_OFFSET( AFSReparseTagInfo, AFSMountPoint.Buffer) + Volume.Length + Cell.Length); break; } case AFS_FILE_TYPE_DFSLINK: { if( pCcb->DirectoryCB->NameInformation.TargetName.Length == 0) { ntStatus = STATUS_REPARSE_POINT_NOT_RESOLVED; break; } bRelative = ( pCcb->DirectoryCB->NameInformation.TargetName.Buffer[0] == L'\\'); bDriveLetter = (bRelative == FALSE && pCcb->DirectoryCB->NameInformation.TargetName.Buffer[1] == L':'); if ( bRelative) { if( ulRemainingLen < (ULONG) FIELD_OFFSET( REPARSE_DATA_BUFFER, SymbolicLinkReparseBuffer.PathBuffer) + pCcb->DirectoryCB->NameInformation.TargetName.Length) { ntStatus = STATUS_BUFFER_TOO_SMALL; Irp->IoStatus.Information = FIELD_OFFSET( REPARSE_DATA_BUFFER, SymbolicLinkReparseBuffer.PathBuffer) + pCcb->DirectoryCB->NameInformation.TargetName.Length; break; } pMSFTReparseBuffer->SymbolicLinkReparseBuffer.Flags = SYMLINK_FLAG_RELATIVE; pMSFTReparseBuffer->SymbolicLinkReparseBuffer.SubstituteNameLength = pCcb->DirectoryCB->NameInformation.TargetName.Length; pMSFTReparseBuffer->SymbolicLinkReparseBuffer.PrintNameLength = pCcb->DirectoryCB->NameInformation.TargetName.Length; pMSFTReparseBuffer->SymbolicLinkReparseBuffer.SubstituteNameOffset = 0; pMSFTReparseBuffer->SymbolicLinkReparseBuffer.PrintNameOffset = 0; PathBuffer = pMSFTReparseBuffer->SymbolicLinkReparseBuffer.PathBuffer; RtlCopyMemory( PathBuffer, pCcb->DirectoryCB->NameInformation.TargetName.Buffer, pCcb->DirectoryCB->NameInformation.TargetName.Length); pReparseBuffer->ReparseDataLength = FIELD_OFFSET( REPARSE_DATA_BUFFER, SymbolicLinkReparseBuffer.PathBuffer) - FIELD_OFFSET( REPARSE_DATA_BUFFER, GenericReparseBuffer.DataBuffer) + pMSFTReparseBuffer->SymbolicLinkReparseBuffer.SubstituteNameLength; } else if ( bDriveLetter) { if( ulRemainingLen < (ULONG) FIELD_OFFSET( REPARSE_DATA_BUFFER, SymbolicLinkReparseBuffer.PathBuffer) + /* Display Name */ pCcb->DirectoryCB->NameInformation.TargetName.Length + /* Substitute Name */ pCcb->DirectoryCB->NameInformation.TargetName.Length + 4 * sizeof( WCHAR)) { ntStatus = STATUS_BUFFER_TOO_SMALL; Irp->IoStatus.Information = FIELD_OFFSET( REPARSE_DATA_BUFFER, SymbolicLinkReparseBuffer.PathBuffer) + pCcb->DirectoryCB->NameInformation.TargetName.Length + pCcb->DirectoryCB->NameInformation.TargetName.Length + 4 * sizeof( WCHAR); break; } pMSFTReparseBuffer->SymbolicLinkReparseBuffer.Flags = 0; pMSFTReparseBuffer->SymbolicLinkReparseBuffer.SubstituteNameLength = pCcb->DirectoryCB->NameInformation.TargetName.Length + 4 * sizeof( WCHAR); pMSFTReparseBuffer->SymbolicLinkReparseBuffer.PrintNameLength = pCcb->DirectoryCB->NameInformation.TargetName.Length; pMSFTReparseBuffer->SymbolicLinkReparseBuffer.SubstituteNameOffset = pMSFTReparseBuffer->SymbolicLinkReparseBuffer.PrintNameLength; pMSFTReparseBuffer->SymbolicLinkReparseBuffer.PrintNameOffset = 0; PathBuffer = pMSFTReparseBuffer->SymbolicLinkReparseBuffer.PathBuffer; /* Display Name */ RtlCopyMemory( PathBuffer, pCcb->DirectoryCB->NameInformation.TargetName.Buffer, pCcb->DirectoryCB->NameInformation.TargetName.Length); PathBuffer += pCcb->DirectoryCB->NameInformation.TargetName.Length / sizeof( WCHAR); /* Substitute Name */ *PathBuffer++ = L'\\'; *PathBuffer++ = L'?'; *PathBuffer++ = L'?'; *PathBuffer++ = L'\\'; RtlCopyMemory( PathBuffer, pCcb->DirectoryCB->NameInformation.TargetName.Buffer, pCcb->DirectoryCB->NameInformation.TargetName.Length); pReparseBuffer->ReparseDataLength = FIELD_OFFSET( REPARSE_DATA_BUFFER, SymbolicLinkReparseBuffer.PathBuffer) - FIELD_OFFSET( REPARSE_DATA_BUFFER, GenericReparseBuffer.DataBuffer) + pMSFTReparseBuffer->SymbolicLinkReparseBuffer.PrintNameLength + pMSFTReparseBuffer->SymbolicLinkReparseBuffer.SubstituteNameLength; } else { if( ulRemainingLen < (ULONG) FIELD_OFFSET( REPARSE_DATA_BUFFER, SymbolicLinkReparseBuffer.PathBuffer) + /* Display Name */ pCcb->DirectoryCB->NameInformation.TargetName.Length + 1 * sizeof( WCHAR) + /* Substitute Name */ pCcb->DirectoryCB->NameInformation.TargetName.Length + 7 * sizeof( WCHAR)) { ntStatus = STATUS_BUFFER_TOO_SMALL; Irp->IoStatus.Information = FIELD_OFFSET( REPARSE_DATA_BUFFER, SymbolicLinkReparseBuffer.PathBuffer) + pCcb->DirectoryCB->NameInformation.TargetName.Length + 1 * sizeof( WCHAR) + pCcb->DirectoryCB->NameInformation.TargetName.Length + 7 * sizeof( WCHAR); break; } pMSFTReparseBuffer->SymbolicLinkReparseBuffer.Flags = 0; pMSFTReparseBuffer->SymbolicLinkReparseBuffer.SubstituteNameLength = pCcb->DirectoryCB->NameInformation.TargetName.Length + 7 * sizeof( WCHAR); pMSFTReparseBuffer->SymbolicLinkReparseBuffer.PrintNameLength = pCcb->DirectoryCB->NameInformation.TargetName.Length + 1 * sizeof( WCHAR); pMSFTReparseBuffer->SymbolicLinkReparseBuffer.SubstituteNameOffset = pMSFTReparseBuffer->SymbolicLinkReparseBuffer.PrintNameLength; pMSFTReparseBuffer->SymbolicLinkReparseBuffer.PrintNameOffset = 0; PathBuffer = pMSFTReparseBuffer->SymbolicLinkReparseBuffer.PathBuffer; /* Display Name */ *PathBuffer++ = L'\\'; RtlCopyMemory( PathBuffer, pCcb->DirectoryCB->NameInformation.TargetName.Buffer, pCcb->DirectoryCB->NameInformation.TargetName.Length); PathBuffer += pCcb->DirectoryCB->NameInformation.TargetName.Length / sizeof( WCHAR); /* Substitute Name */ *PathBuffer++ = L'\\'; *PathBuffer++ = L'?'; *PathBuffer++ = L'?'; *PathBuffer++ = L'\\'; *PathBuffer++ = L'U'; *PathBuffer++ = L'N'; *PathBuffer++ = L'C'; RtlCopyMemory( PathBuffer, pCcb->DirectoryCB->NameInformation.TargetName.Buffer, pCcb->DirectoryCB->NameInformation.TargetName.Length); pReparseBuffer->ReparseDataLength = FIELD_OFFSET( REPARSE_DATA_BUFFER, SymbolicLinkReparseBuffer.PathBuffer) - FIELD_OFFSET( REPARSE_DATA_BUFFER, GenericReparseBuffer.DataBuffer) + pMSFTReparseBuffer->SymbolicLinkReparseBuffer.PrintNameLength + pMSFTReparseBuffer->SymbolicLinkReparseBuffer.SubstituteNameLength; } break; } default: ntStatus = STATUS_NOT_A_REPARSE_POINT; break; } if ( ntStatus == STATUS_SUCCESS) { ulRemainingLen -= pReparseBuffer->ReparseDataLength; if ( pFcb->ObjectInformation->FileType == AFS_FILE_TYPE_MOUNTPOINT) { pReparseBuffer->ReparseTag = IO_REPARSE_TAG_SURROGATE|IO_REPARSE_TAG_OPENAFS_DFS; RtlCopyMemory( &pReparseBuffer->ReparseGuid, &GUID_AFS_REPARSE_GUID, sizeof( GUID)); Irp->IoStatus.Information = FIELD_OFFSET( REPARSE_GUID_DATA_BUFFER, GenericReparseBuffer.DataBuffer) + pReparseBuffer->ReparseDataLength; } else { pReparseBuffer->ReparseTag = IO_REPARSE_TAG_SYMLINK; Irp->IoStatus.Information = FIELD_OFFSET( REPARSE_DATA_BUFFER, GenericReparseBuffer.DataBuffer) + pReparseBuffer->ReparseDataLength; } } AFSReleaseResource( &pCcb->DirectoryCB->NonPaged->Lock); break; } case FSCTL_SET_REPARSE_POINT: { 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; AFSDbgTrace(( AFS_SUBSYSTEM_FILE_PROCESSING, AFS_TRACE_LEVEL_VERBOSE, "AFSProcessUserFsRequest Processing FSCTL_SET_REPARSE_POINT request %wZ Type 0x%x Attrib 0x%x\n", &pCcb->DirectoryCB->NameInformation.FileName, pFcb->ObjectInformation->FileType, pFcb->ObjectInformation->FileAttributes)); if( ulInputBufferLen < FIELD_OFFSET( REPARSE_GUID_DATA_BUFFER, GenericReparseBuffer.DataBuffer)) { ntStatus = STATUS_IO_REPARSE_DATA_INVALID; break; } if( (pReparseGUIDBuffer->ReparseTag & 0x0000FFFF) == IO_REPARSE_TAG_OPENAFS_DFS) { 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 // 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); AFSDbgTrace(( 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); AFSDbgTrace(( 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; } // // First thing is to locate/create our object information block // for this entry // AFSAcquireExcl( pFcb->ObjectInformation->VolumeCB->ObjectInfoTree.TreeLock, TRUE); if ( AFSIsVolumeFID( &pFcb->ObjectInformation->ParentFileId)) { pParentObjectInfo = &pFcb->ObjectInformation->VolumeCB->ObjectInformation; } else { ullIndex = AFSCreateLowIndex( &pFcb->ObjectInformation->ParentFileId); ntStatus = AFSLocateHashEntry( pFcb->ObjectInformation->VolumeCB->ObjectInfoTree.TreeHead, ullIndex, (AFSBTreeEntry **)&pParentObjectInfo); } if ( NT_SUCCESS( ntStatus)) { lCount = AFSObjectInfoIncrement( pParentObjectInfo, AFS_OBJECT_REFERENCE_FS_REQ); AFSDbgTrace(( AFS_SUBSYSTEM_OBJECT_REF_COUNTING, AFS_TRACE_LEVEL_VERBOSE, "AFSProcessUserFsRequest Increment count on object %p Cnt %d\n", pParentObjectInfo, lCount)); KeQueryTickCount( &pParentObjectInfo->LastAccessCount); } AFSReleaseResource( pFcb->ObjectInformation->VolumeCB->ObjectInfoTree.TreeLock); if ( NT_SUCCESS( ntStatus)) { // // Extract out the information to the call to the service // ntStatus = AFSCreateSymlink( &pCcb->AuthGroup, pParentObjectInfo, &pCcb->DirectoryCB->NameInformation.FileName, pFcb->ObjectInformation, &uniTargetName); AFSDbgTrace(( 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, pFcb->ObjectInformation->FileType, pFcb->ObjectInformation->FileAttributes, ntStatus)); AFSAcquireShared( pFcb->ObjectInformation->VolumeCB->ObjectInfoTree.TreeLock, TRUE); lCount = AFSObjectInfoDecrement( pParentObjectInfo, AFS_OBJECT_REFERENCE_FS_REQ); AFSDbgTrace(( AFS_SUBSYSTEM_OBJECT_REF_COUNTING, AFS_TRACE_LEVEL_VERBOSE, "AFSProcessUserFsRequest Decrement count on object %p Cnt %d\n", pParentObjectInfo, lCount)); AFSReleaseResource( pFcb->ObjectInformation->VolumeCB->ObjectInfoTree.TreeLock); } break; } case FSCTL_DELETE_REPARSE_POINT: { REPARSE_GUID_DATA_BUFFER *pReparseBuffer = (REPARSE_GUID_DATA_BUFFER *)Irp->AssociatedIrp.SystemBuffer; AFSDbgTrace(( AFS_SUBSYSTEM_FILE_PROCESSING, AFS_TRACE_LEVEL_VERBOSE_2, "AFSProcessUserFsRequest Processing FSCTL_DELETE_REPARSE_POINT request %wZ Type 0x%x Attrib 0x%x\n", &pCcb->DirectoryCB->NameInformation.FileName, pFcb->ObjectInformation->FileType, pFcb->ObjectInformation->FileAttributes)); // // Check if we have the reparse entry set on the entry // if( !BooleanFlagOn( pFcb->ObjectInformation->FileAttributes, FILE_ATTRIBUTE_REPARSE_POINT)) { ntStatus = STATUS_NOT_A_REPARSE_POINT; break; } 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; break; } if( RtlCompareMemory( &pReparseBuffer->ReparseGuid, &GUID_AFS_REPARSE_GUID, sizeof( GUID)) != sizeof( GUID)) { ntStatus = STATUS_REPARSE_ATTRIBUTE_CONFLICT; break; } // // 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_SUCCESS; break; } default : { AFSDbgTrace(( AFS_SUBSYSTEM_FILE_PROCESSING, AFS_TRACE_LEVEL_VERBOSE_2, "AFSProcessUserFsRequest Processing default (%08lX) request\n", ulFsControlCode)); ntStatus = STATUS_INVALID_DEVICE_REQUEST; break; } } try_exit: NOTHING; } return ntStatus; }
GUID * AFSValidateProcessEntry( IN HANDLE ProcessId, IN BOOLEAN bProcessTreeLocked) { GUID *pAuthGroup = NULL; NTSTATUS ntStatus = STATUS_SUCCESS; AFSProcessCB *pProcessCB = NULL, *pParentProcessCB = NULL; AFSDeviceExt *pDeviceExt = (AFSDeviceExt *)AFSDeviceObject->DeviceExtension; ULONGLONG ullProcessID = (ULONGLONG)ProcessId; UNICODE_STRING uniSIDString; ULONG ulSIDHash = 0; AFSSIDEntryCB *pSIDEntryCB = NULL; ULONG ulSessionId = 0; ULONGLONG ullTableHash = 0; AFSThreadCB *pParentThreadCB = NULL; UNICODE_STRING uniGUID; BOOLEAN bImpersonation = FALSE; __Enter { uniSIDString.Length = 0; uniSIDString.MaximumLength = 0; uniSIDString.Buffer = NULL; if ( !bProcessTreeLocked) { AFSDbgTrace(( AFS_SUBSYSTEM_LOCK_PROCESSING, AFS_TRACE_LEVEL_VERBOSE, "AFSValidateProcessEntry Acquiring Control ProcessTree.TreeLock lock %p SHARED %08lX\n", pDeviceExt->Specific.Control.ProcessTree.TreeLock, PsGetCurrentThread())); AFSAcquireShared( pDeviceExt->Specific.Control.ProcessTree.TreeLock, TRUE); } AFSDbgTrace(( AFS_SUBSYSTEM_AUTHGROUP_PROCESSING, AFS_TRACE_LEVEL_VERBOSE, "%s Entry for ProcessID %I64X\n", __FUNCTION__, ullProcessID)); ntStatus = AFSLocateHashEntry( pDeviceExt->Specific.Control.ProcessTree.TreeHead, ullProcessID, (AFSBTreeEntry **)&pProcessCB); if( !NT_SUCCESS( ntStatus) || pProcessCB == NULL) { if ( !bProcessTreeLocked) { AFSReleaseResource( pDeviceExt->Specific.Control.ProcessTree.TreeLock); AFSAcquireExcl( pDeviceExt->Specific.Control.ProcessTree.TreeLock, TRUE); } ntStatus = AFSLocateHashEntry( pDeviceExt->Specific.Control.ProcessTree.TreeHead, ullProcessID, (AFSBTreeEntry **)&pProcessCB); if( !NT_SUCCESS( ntStatus) || pProcessCB == NULL) { AFSProcessCreate( 0, ProcessId, 0, 0); } if( !NT_SUCCESS( ntStatus) || pProcessCB == NULL) { AFSDbgTrace(( AFS_SUBSYSTEM_AUTHGROUP_PROCESSING, AFS_TRACE_LEVEL_ERROR, "%s Failed to locate process entry for ProcessID %I64X\n", __FUNCTION__, ullProcessID)); try_return( ntStatus = STATUS_UNSUCCESSFUL); } if ( !bProcessTreeLocked) { AFSConvertToShared( pDeviceExt->Specific.Control.ProcessTree.TreeLock); } } // // Locate and lock the ParentProcessCB if we have one // if( pProcessCB->ParentProcessId != 0) { AFSDbgTrace(( AFS_SUBSYSTEM_AUTHGROUP_PROCESSING, AFS_TRACE_LEVEL_VERBOSE, "%s Locating process entry for Parent ProcessID %I64X\n", __FUNCTION__, pProcessCB->ParentProcessId)); ntStatus = AFSLocateHashEntry( pDeviceExt->Specific.Control.ProcessTree.TreeHead, (ULONGLONG)pProcessCB->ParentProcessId, (AFSBTreeEntry **)&pParentProcessCB); if( NT_SUCCESS( ntStatus) && pParentProcessCB != NULL) { AFSAcquireExcl( &pParentProcessCB->Lock, TRUE); AFSDbgTrace(( AFS_SUBSYSTEM_AUTHGROUP_PROCESSING, AFS_TRACE_LEVEL_VERBOSE, "%s Located process entry for Parent ProcessID %I64X\n", __FUNCTION__, pProcessCB->ParentProcessId)); } } else { AFSDbgTrace(( AFS_SUBSYSTEM_AUTHGROUP_PROCESSING, AFS_TRACE_LEVEL_VERBOSE, "%s No parent ID for ProcessID %I64X\n", __FUNCTION__, ullProcessID)); } AFSAcquireExcl( &pProcessCB->Lock, TRUE); #if defined(_WIN64) // // Mark the process as 64-bit if it is. // if( !IoIs32bitProcess( NULL)) { SetFlag( pProcessCB->Flags, AFS_PROCESS_FLAG_IS_64BIT); } else { ClearFlag( pProcessCB->Flags, AFS_PROCESS_FLAG_IS_64BIT); } #endif // // Locate the SID for the caller // ntStatus = AFSGetCallerSID( &uniSIDString, &bImpersonation); if( !NT_SUCCESS( ntStatus)) { AFSDbgTrace(( AFS_SUBSYSTEM_AUTHGROUP_PROCESSING, AFS_TRACE_LEVEL_ERROR, "%s Failed to locate callers SID for ProcessID %I64X\n", __FUNCTION__, ullProcessID)); try_return( ntStatus); } ulSessionId = AFSGetSessionId( (HANDLE)ullProcessID, &bImpersonation); if( ulSessionId == (ULONG)-1) { AFSDbgTrace(( AFS_SUBSYSTEM_AUTHGROUP_PROCESSING, AFS_TRACE_LEVEL_ERROR, "%s Failed to retrieve session ID for ProcessID %I64X\n", __FUNCTION__, ullProcessID)); try_return( ntStatus = STATUS_INSUFFICIENT_RESOURCES); } AFSDbgTrace(( AFS_SUBSYSTEM_AUTHGROUP_PROCESSING, AFS_TRACE_LEVEL_VERBOSE, "%s Retrieved callers SID %wZ for ProcessID %I64X Session %08lX\n", __FUNCTION__, &uniSIDString, ullProcessID, ulSessionId)); // // If there is an Auth Group for the current process, // our job is finished. // if ( bImpersonation == FALSE) { pAuthGroup = pProcessCB->ActiveAuthGroup; if( pAuthGroup != NULL && !AFSIsNoPAGAuthGroup( pAuthGroup)) { uniGUID.Buffer = NULL; RtlStringFromGUID( *pAuthGroup, &uniGUID); AFSDbgTrace(( AFS_SUBSYSTEM_AUTHGROUP_PROCESSING, AFS_TRACE_LEVEL_VERBOSE, "%s Located valid AuthGroup GUID %wZ for SID %wZ ProcessID %I64X Session %08lX\n", __FUNCTION__, &uniGUID, &uniSIDString, ullProcessID, ulSessionId)); if( uniGUID.Buffer != NULL) { RtlFreeUnicodeString( &uniGUID); } try_return( ntStatus = STATUS_SUCCESS); } // // The current process does not yet have an Auth Group. Try to inherit // one from the parent process thread that created this process. // if( pParentProcessCB != NULL) { for ( pParentThreadCB = pParentProcessCB->ThreadList; pParentThreadCB != NULL; pParentThreadCB = pParentThreadCB->Next) { if( pParentThreadCB->ThreadId == pProcessCB->CreatingThreadId) { break; } } // // If the creating thread was found and it has a thread specific // Auth Group, use that even if it is the No PAG // if( pParentThreadCB != NULL && pParentThreadCB->ActiveAuthGroup != NULL && !AFSIsNoPAGAuthGroup( pParentThreadCB->ActiveAuthGroup)) { pProcessCB->ActiveAuthGroup = pParentThreadCB->ActiveAuthGroup; uniGUID.Buffer = NULL; RtlStringFromGUID( *(pProcessCB->ActiveAuthGroup), &uniGUID); AFSDbgTrace(( AFS_SUBSYSTEM_AUTHGROUP_PROCESSING, AFS_TRACE_LEVEL_VERBOSE, "%s PID %I64X Session %08lX inherited Active AuthGroup %wZ from thread %I64X\n", __FUNCTION__, ullProcessID, ulSessionId, &uniGUID, pParentThreadCB->ThreadId)); if( uniGUID.Buffer != NULL) { RtlFreeUnicodeString( &uniGUID); } } // // If the parent thread was not found or does not have an auth group // else if( pParentProcessCB->ActiveAuthGroup != NULL && !AFSIsNoPAGAuthGroup( pParentProcessCB->ActiveAuthGroup)) { pProcessCB->ActiveAuthGroup = pParentProcessCB->ActiveAuthGroup; uniGUID.Buffer = NULL; RtlStringFromGUID( *(pProcessCB->ActiveAuthGroup), &uniGUID); AFSDbgTrace(( AFS_SUBSYSTEM_AUTHGROUP_PROCESSING, AFS_TRACE_LEVEL_VERBOSE, "%s PID %I64X Session %08lX inherited Active AuthGroup %wZ from parent PID %I64X\n", __FUNCTION__, ullProcessID, ulSessionId, &uniGUID, pParentProcessCB->TreeEntry.HashIndex)); if( uniGUID.Buffer != NULL) { RtlFreeUnicodeString( &uniGUID); } } // // If an Auth Group was inherited, set it to be the active group // if( pProcessCB->ActiveAuthGroup != NULL && !AFSIsNoPAGAuthGroup( pParentProcessCB->ActiveAuthGroup)) { pAuthGroup = pProcessCB->ActiveAuthGroup; uniGUID.Buffer = NULL; RtlStringFromGUID( *(pProcessCB->ActiveAuthGroup), &uniGUID); AFSDbgTrace(( AFS_SUBSYSTEM_AUTHGROUP_PROCESSING, AFS_TRACE_LEVEL_VERBOSE, "%s Returning(1) Active AuthGroup %wZ for SID %wZ PID %I64X Session %08lX\n", __FUNCTION__, &uniGUID, &uniSIDString, ullProcessID, ulSessionId)); if( uniGUID.Buffer != NULL) { RtlFreeUnicodeString( &uniGUID); } try_return( ntStatus); } } } // // If no Auth Group was inherited, assign one based upon the Session and SID // ntStatus = RtlHashUnicodeString( &uniSIDString, TRUE, HASH_STRING_ALGORITHM_DEFAULT, &ulSIDHash); if( !NT_SUCCESS( ntStatus)) { AFSDbgTrace(( AFS_SUBSYSTEM_AUTHGROUP_PROCESSING, AFS_TRACE_LEVEL_ERROR, "%s Failed to hash SID %wZ for PID %I64X Session %08lX Status %08lX\n", __FUNCTION__, &uniSIDString, ullProcessID, ulSessionId, ntStatus)); try_return( ntStatus); } ullTableHash = ( ((ULONGLONG)ulSessionId << 32) | ulSIDHash); AFSAcquireShared( pDeviceExt->Specific.Control.AuthGroupTree.TreeLock, TRUE); ntStatus = AFSLocateHashEntry( pDeviceExt->Specific.Control.AuthGroupTree.TreeHead, (ULONGLONG)ullTableHash, (AFSBTreeEntry **)&pSIDEntryCB); if( !NT_SUCCESS( ntStatus) || pSIDEntryCB == NULL) { AFSReleaseResource( pDeviceExt->Specific.Control.AuthGroupTree.TreeLock); AFSAcquireExcl( pDeviceExt->Specific.Control.AuthGroupTree.TreeLock, TRUE); ntStatus = AFSLocateHashEntry( pDeviceExt->Specific.Control.AuthGroupTree.TreeHead, (ULONGLONG)ullTableHash, (AFSBTreeEntry **)&pSIDEntryCB); if( !NT_SUCCESS( ntStatus) || pSIDEntryCB == NULL) { pSIDEntryCB = (AFSSIDEntryCB *)AFSExAllocatePoolWithTag( NonPagedPool, sizeof( AFSSIDEntryCB), AFS_AG_ENTRY_CB_TAG); if( pSIDEntryCB == NULL) { AFSReleaseResource( pDeviceExt->Specific.Control.AuthGroupTree.TreeLock); try_return( ntStatus = STATUS_INSUFFICIENT_RESOURCES); } RtlZeroMemory( pSIDEntryCB, sizeof( AFSSIDEntryCB)); pSIDEntryCB->TreeEntry.HashIndex = (ULONGLONG)ullTableHash; while( ExUuidCreate( &pSIDEntryCB->AuthGroup) == STATUS_RETRY); uniGUID.Buffer = NULL; RtlStringFromGUID( pSIDEntryCB->AuthGroup, &uniGUID); AFSDbgTrace(( AFS_SUBSYSTEM_AUTHGROUP_PROCESSING, AFS_TRACE_LEVEL_VERBOSE, "%s SID %wZ PID %I64X Session %08lX generated NEW AG %wZ\n", __FUNCTION__, &uniSIDString, ullProcessID, ulSessionId, &uniGUID)); if( uniGUID.Buffer != NULL) { RtlFreeUnicodeString( &uniGUID); } if( pDeviceExt->Specific.Control.AuthGroupTree.TreeHead == NULL) { pDeviceExt->Specific.Control.AuthGroupTree.TreeHead = (AFSBTreeEntry *)pSIDEntryCB; } else { AFSInsertHashEntry( pDeviceExt->Specific.Control.AuthGroupTree.TreeHead, &pSIDEntryCB->TreeEntry); } } AFSConvertToShared( pDeviceExt->Specific.Control.AuthGroupTree.TreeLock); } AFSReleaseResource( pDeviceExt->Specific.Control.AuthGroupTree.TreeLock); // // Store the auth group into the process cb // pProcessCB->ActiveAuthGroup = &pSIDEntryCB->AuthGroup; uniGUID.Buffer = NULL; RtlStringFromGUID( pSIDEntryCB->AuthGroup, &uniGUID); AFSDbgTrace(( AFS_SUBSYSTEM_AUTHGROUP_PROCESSING, AFS_TRACE_LEVEL_VERBOSE, "%s SID %wZ PID %I64X Session %08lX assigned AG %wZ\n", __FUNCTION__, &uniSIDString, ullProcessID, ulSessionId, &uniGUID)); if( uniGUID.Buffer != NULL) { RtlFreeUnicodeString( &uniGUID); } // // Set the AFS_PROCESS_LOCAL_SYSTEM_AUTH flag if the process SID // is LOCAL_SYSTEM // if( AFSIsLocalSystemSID( &uniSIDString)) { SetFlag( pProcessCB->Flags, AFS_PROCESS_LOCAL_SYSTEM_AUTH); AFSDbgTrace(( AFS_SUBSYSTEM_AUTHGROUP_PROCESSING, AFS_TRACE_LEVEL_VERBOSE, "%s Setting PID %I64X Session %08lX with LOCAL SYSTEM AUTHORITY\n", __FUNCTION__, ullProcessID, ulSessionId)); } // // Return the auth group // pAuthGroup = pProcessCB->ActiveAuthGroup; uniGUID.Buffer = NULL; RtlStringFromGUID( *(pProcessCB->ActiveAuthGroup), &uniGUID); AFSDbgTrace(( AFS_SUBSYSTEM_AUTHGROUP_PROCESSING, AFS_TRACE_LEVEL_VERBOSE, "%s Returning(2) Active AuthGroup %wZ for SID %wZ PID %I64X Session %08lX\n", __FUNCTION__, &uniGUID, &uniSIDString, ullProcessID, ulSessionId)); if( uniGUID.Buffer != NULL) { RtlFreeUnicodeString( &uniGUID); } try_exit: if( pProcessCB != NULL) { if( bImpersonation == FALSE && !BooleanFlagOn( pProcessCB->Flags, AFS_PROCESS_FLAG_ACE_SET) && NT_SUCCESS( ntStatus)) { ntStatus = AFSProcessSetProcessDacl( pProcessCB); if( !NT_SUCCESS( ntStatus)) { pAuthGroup = NULL; } else { SetFlag( pProcessCB->Flags, AFS_PROCESS_FLAG_ACE_SET); } } AFSReleaseResource( &pProcessCB->Lock); } if( pParentProcessCB != NULL) { AFSReleaseResource( &pParentProcessCB->Lock); } if( uniSIDString.Length > 0) { RtlFreeUnicodeString( &uniSIDString); } if ( !bProcessTreeLocked) { AFSReleaseResource( pDeviceExt->Specific.Control.ProcessTree.TreeLock); } } return pAuthGroup; }
NTSTATUS AFSCheckLibraryState( IN PIRP Irp) { NTSTATUS ntStatus = STATUS_SUCCESS; AFSDeviceExt *pDevExt = (AFSDeviceExt *)AFSDeviceObject->DeviceExtension; AFSDeviceExt *pRDRDevExt = (AFSDeviceExt *)AFSRDRDeviceObject->DeviceExtension; PIO_STACK_LOCATION pIrpSp = IoGetCurrentIrpStackLocation( Irp); __Enter { AFSAcquireShared( &pDevExt->Specific.Control.LibraryStateLock, TRUE); AFSDbgTrace(( AFS_SUBSYSTEM_LOAD_LIBRARY, AFS_TRACE_LEVEL_VERBOSE, "%s Entry State %08lX Irp %p Function %08lX\n", __FUNCTION__, pRDRDevExt->DeviceFlags, Irp, pIrpSp->MajorFunction)); if( BooleanFlagOn( pRDRDevExt->DeviceFlags, AFS_DEVICE_FLAG_REDIRECTOR_SHUTDOWN)) { try_return( ntStatus = STATUS_DEVICE_NOT_READY); } if( !BooleanFlagOn( pDevExt->Specific.Control.LibraryState, AFS_LIBRARY_LOADED)) { if( Irp != NULL) { AFSDbgTrace(( AFS_SUBSYSTEM_LOAD_LIBRARY, AFS_TRACE_LEVEL_VERBOSE, "%s Queuing request %p\n", __FUNCTION__, Irp)); ntStatus = AFSQueueLibraryRequest( Irp); AFSDbgTrace(( AFS_SUBSYSTEM_LOAD_LIBRARY, AFS_TRACE_LEVEL_VERBOSE, "%s Queued request %p Status %08lX\n", __FUNCTION__, Irp, ntStatus)); } else { ntStatus = STATUS_TOO_LATE; AFSDbgTrace(( AFS_SUBSYSTEM_LOAD_LIBRARY, AFS_TRACE_LEVEL_VERBOSE, "%s Failing request %p\n", __FUNCTION__, Irp)); } try_return( ntStatus); } if( InterlockedIncrement( &pDevExt->Specific.Control.InflightLibraryRequests) == 1) { KeClearEvent( &pDevExt->Specific.Control.InflightLibraryEvent); } try_exit: AFSDbgTrace(( AFS_SUBSYSTEM_LOAD_LIBRARY, AFS_TRACE_LEVEL_VERBOSE, "%s Completed Irp %p Status %08lX Inflight Count %08lX\n", __FUNCTION__, Irp, ntStatus, pDevExt->Specific.Control.InflightLibraryRequests)); AFSReleaseResource( &pDevExt->Specific.Control.LibraryStateLock); } return ntStatus; }