NTSTATUS AFSSetEA( IN PDEVICE_OBJECT LibDeviceObject, IN PIRP Irp) { NTSTATUS ntStatus = STATUS_EAS_NOT_SUPPORTED; IO_STACK_LOCATION *pIrpSp; pIrpSp = IoGetCurrentIrpStackLocation( Irp); __try { AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING, AFS_TRACE_LEVEL_ERROR, "AFSSetEa Entry for FO %08lX\n", pIrpSp->FileObject); AFSCompleteRequest( Irp, ntStatus); } __except( AFSExceptionFilter( GetExceptionCode(), GetExceptionInformation()) ) { AFSDbgLogMsg( 0, 0, "EXCEPTION - AFSSetEA\n"); } return ntStatus; }
NTSTATUS AFSSetVolumeInfo( IN PDEVICE_OBJECT DeviceObject, IN PIRP Irp) { NTSTATUS ntStatus = STATUS_SUCCESS; IO_STACK_LOCATION *pIrpSp; pIrpSp = IoGetCurrentIrpStackLocation( Irp); __try { AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING, AFS_TRACE_LEVEL_WARNING, "AFSSetVolumeInfo Entry for FO %08lX\n", pIrpSp->FileObject); AFSCompleteRequest( Irp, ntStatus); } __except( AFSExceptionFilter( __FUNCTION__, GetExceptionCode(), GetExceptionInformation()) ) { AFSDbgLogMsg( 0, 0, "EXCEPTION - AFSSetVolumeInfo\n"); AFSDumpTraceFilesFnc(); } return ntStatus; }
void AFSTagInitialLogEntry() { LARGE_INTEGER liTime, liLocalTime; TIME_FIELDS timeFields; KeQuerySystemTime( &liTime); ExSystemTimeToLocalTime( &liTime, &liLocalTime); RtlTimeToTimeFields( &liLocalTime, &timeFields); AFSDbgLogMsg( 0, 0, "AFS Log Initialized %d-%d-%d %d:%d Level %d Subsystems %08lX\n", timeFields.Month, timeFields.Day, timeFields.Year, timeFields.Hour, timeFields.Minute, AFSTraceLevel, AFSTraceComponent); return; }
NTSTATUS AFSInitCcb( IN OUT AFSCcb **Ccb) { NTSTATUS Status = STATUS_SUCCESS; AFSCcb *pCcb = NULL; __Enter { // // Allocate our context control block // pCcb = (AFSCcb *)AFSExAllocatePoolWithTag( PagedPool, sizeof( AFSCcb), AFS_CCB_ALLOCATION_TAG); if( pCcb == NULL) { AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING, AFS_TRACE_LEVEL_ERROR, "AFSInitCcb Failed to allocate Ccb\n"); try_return( Status = STATUS_INSUFFICIENT_RESOURCES); } RtlZeroMemory( pCcb, sizeof( AFSCcb)); pCcb->Size = sizeof( AFSCcb); pCcb->Type = AFS_CCB; // // Return the Ccb // *Ccb = pCcb; try_exit: if( !NT_SUCCESS( Status)) { if( pCcb != NULL) { AFSExFreePool( pCcb); } *Ccb = NULL; } } return Status; }
NTSTATUS AFSFSControl( IN PDEVICE_OBJECT LibDeviceObject, IN PIRP Irp) { NTSTATUS ntStatus = STATUS_SUCCESS; IO_STACK_LOCATION *pIrpSp; pIrpSp = IoGetCurrentIrpStackLocation( Irp); __try { switch( pIrpSp->MinorFunction) { case IRP_MN_USER_FS_REQUEST: ntStatus = AFSProcessUserFsRequest( Irp); break; case IRP_MN_MOUNT_VOLUME: break; case IRP_MN_VERIFY_VOLUME: break; default: break; } AFSCompleteRequest( Irp, ntStatus); } __except( AFSExceptionFilter( __FUNCTION__, GetExceptionCode(), GetExceptionInformation()) ) { AFSDbgLogMsg( 0, 0, "EXCEPTION - AFSFSControl\n"); AFSDumpTraceFilesFnc(); } return ntStatus; }
NTSTATUS AFSCreate( IN PDEVICE_OBJECT DeviceObject, IN PIRP Irp) { NTSTATUS ntStatus = STATUS_SUCCESS; __try { if( DeviceObject == AFSDeviceObject) { ntStatus = AFSControlDeviceCreate( Irp); try_return( ntStatus); } ntStatus = AFSCommonCreate( DeviceObject, Irp); try_exit: NOTHING; } __except( AFSExceptionFilter( GetExceptionCode(), GetExceptionInformation()) ) { AFSDbgLogMsg( 0, 0, "EXCEPTION - AFSCreate\n"); ntStatus = STATUS_ACCESS_DENIED; } return ntStatus; }
NTSTATUS AFSClose( IN PDEVICE_OBJECT DeviceObject, IN PIRP Irp) { NTSTATUS ntStatus = STATUS_SUCCESS; __try { if( DeviceObject == AFSDeviceObject) { AFSCompleteRequest( Irp, ntStatus); try_return( ntStatus); } ntStatus = AFSCommonClose( DeviceObject, Irp); try_exit: NOTHING; } __except( AFSExceptionFilter( GetExceptionCode(), GetExceptionInformation()) ) { AFSDbgLogMsg( 0, 0, "EXCEPTION - AFSClose\n"); } return ntStatus; }
NTSTATUS AFSInsertRequest( IN AFSCommSrvcCB *CommSrvc, IN AFSPoolEntry *Entry) { NTSTATUS ntStatus = STATUS_SUCCESS; __Enter { AFSDbgLogMsg( AFS_SUBSYSTEM_LOCK_PROCESSING, AFS_TRACE_LEVEL_VERBOSE, "AFSInsertRequest Acquiring IrpPoolLock lock %08lX EXCL %08lX\n", &CommSrvc->IrpPoolLock, PsGetCurrentThread()); AFSAcquireExcl( &CommSrvc->IrpPoolLock, TRUE); if( CommSrvc->IrpPoolControlFlag != POOL_ACTIVE) { try_return( ntStatus = STATUS_DEVICE_NOT_READY); } if( CommSrvc->RequestPoolHead == NULL) { CommSrvc->RequestPoolHead = Entry; } else { CommSrvc->RequestPoolTail->fLink = Entry; Entry->bLink = CommSrvc->RequestPoolTail; } CommSrvc->RequestPoolTail = Entry; if( Entry->RequestType == AFS_REQUEST_TYPE_RELEASE_FILE_EXTENTS) { KeSetEvent( &CommSrvc->IrpPoolHasReleaseEntries, 0, FALSE); } else { KeSetEvent( &CommSrvc->IrpPoolHasEntries, 0, FALSE); } InterlockedIncrement( &CommSrvc->QueueCount); try_exit: AFSReleaseResource( &CommSrvc->IrpPoolLock); } return ntStatus; }
NTSTATUS AFSCleanup( IN PDEVICE_OBJECT LibDeviceObject, IN PIRP Irp) { NTSTATUS ntStatus = STATUS_SUCCESS; AFSDeviceExt *pDeviceExt = NULL; IO_STACK_LOCATION *pIrpSp = IoGetCurrentIrpStackLocation( Irp); AFSFcb *pFcb = NULL; AFSCcb *pCcb = NULL; PFILE_OBJECT pFileObject = NULL; AFSFcb *pRootFcb = NULL; AFSDeviceExt *pControlDeviceExt = NULL; IO_STATUS_BLOCK stIoSB; AFSObjectInfoCB *pObjectInfo = NULL; AFSFileCleanupCB stFileCleanup; ULONG ulNotificationFlags = 0; __try { if( AFSRDRDeviceObject == NULL) { // // Let this through, it's a cleanup on the library control device // try_return( ntStatus); } pDeviceExt = (AFSDeviceExt *)AFSRDRDeviceObject->DeviceExtension; pControlDeviceExt = (AFSDeviceExt *)AFSControlDeviceObject->DeviceExtension; // // Set some initial variables to make processing easier // pFileObject = pIrpSp->FileObject; pFcb = (AFSFcb *)pIrpSp->FileObject->FsContext; pCcb = (AFSCcb *)pIrpSp->FileObject->FsContext2; if( pFcb == NULL) { try_return( ntStatus); } pObjectInfo = pFcb->ObjectInformation; pRootFcb = pObjectInfo->VolumeCB->RootFcb; RtlZeroMemory( &stFileCleanup, sizeof( AFSFileCleanupCB)); stFileCleanup.ProcessId = (ULONGLONG)PsGetCurrentProcessId(); stFileCleanup.Identifier = (ULONGLONG)pFileObject; // // Perform the cleanup functionality depending on the type of node it is // switch( pFcb->Header.NodeTypeCode) { case AFS_ROOT_ALL: { AFSDbgLogMsg( AFS_SUBSYSTEM_LOCK_PROCESSING, AFS_TRACE_LEVEL_VERBOSE, "AFSCleanup Acquiring GlobalRoot lock %08lX EXCL %08lX\n", &pFcb->NPFcb->Resource, PsGetCurrentThread()); AFSAcquireExcl( &pFcb->NPFcb->Resource, TRUE); ASSERT( pFcb->OpenHandleCount != 0); InterlockedDecrement( &pFcb->OpenHandleCount); AFSDbgLogMsg( AFS_SUBSYSTEM_FCB_REF_COUNTING, AFS_TRACE_LEVEL_VERBOSE, "AFSCleanup (RootAll) Decrement handle count on Fcb %08lX Cnt %d\n", pFcb, pFcb->OpenHandleCount); AFSReleaseResource( &pFcb->NPFcb->Resource); FsRtlNotifyCleanup( pControlDeviceExt->Specific.Control.NotifySync, &pControlDeviceExt->Specific.Control.DirNotifyList, pCcb); break; } case AFS_IOCTL_FCB: { AFSDbgLogMsg( AFS_SUBSYSTEM_LOCK_PROCESSING, AFS_TRACE_LEVEL_VERBOSE, "AFSCleanup Acquiring PIOCtl lock %08lX EXCL %08lX\n", &pFcb->NPFcb->Resource, PsGetCurrentThread()); AFSAcquireExcl( &pFcb->NPFcb->Resource, TRUE); ASSERT( pFcb->OpenHandleCount != 0); InterlockedDecrement( &pFcb->OpenHandleCount); AFSDbgLogMsg( AFS_SUBSYSTEM_FCB_REF_COUNTING, AFS_TRACE_LEVEL_VERBOSE, "AFSCleanup (IOCtl) Decrement handle count on Fcb %08lX Cnt %d\n", pFcb, pFcb->OpenHandleCount); // // Decrement the open child handle count // if( pObjectInfo->ParentObjectInformation != NULL && pObjectInfo->ParentObjectInformation->Specific.Directory.ChildOpenHandleCount > 0) { InterlockedDecrement( &pObjectInfo->ParentObjectInformation->Specific.Directory.ChildOpenHandleCount); AFSDbgLogMsg( AFS_SUBSYSTEM_FCB_REF_COUNTING, AFS_TRACE_LEVEL_VERBOSE, "AFSCleanup (IOCtl) Decrement child open handle count on Parent object %08lX Cnt %d\n", pObjectInfo->ParentObjectInformation, pObjectInfo->ParentObjectInformation->Specific.Directory.ChildOpenHandleCount); } // // And finally, release the Fcb if we acquired it. // AFSReleaseResource( &pFcb->NPFcb->Resource); break; } // // This Fcb represents a file // case AFS_FILE_FCB: { // // We may be performing some cleanup on the Fcb so grab it exclusive to ensure no collisions // AFSDbgLogMsg( AFS_SUBSYSTEM_LOCK_PROCESSING, AFS_TRACE_LEVEL_VERBOSE, "AFSCleanup Acquiring Fcb lock %08lX EXCL %08lX\n", &pFcb->NPFcb->Resource, PsGetCurrentThread()); AFSAcquireExcl( &pFcb->NPFcb->Resource, TRUE); // // If the handle has write permission ... // if( (pCcb->GrantedAccess & FILE_WRITE_DATA) && CcIsFileCached( pIrpSp->FileObject)) { __try { CcFlushCache( &pFcb->NPFcb->SectionObjectPointers, NULL, 0, &stIoSB); if( !NT_SUCCESS( stIoSB.Status)) { AFSDbgLogMsg( AFS_SUBSYSTEM_IO_PROCESSING, AFS_TRACE_LEVEL_ERROR, "AFSCleanup CcFlushCache failure %wZ FID %08lX-%08lX-%08lX-%08lX Status 0x%08lX Bytes 0x%08lX\n", &pCcb->FullFileName, pObjectInfo->FileId.Cell, pObjectInfo->FileId.Volume, pObjectInfo->FileId.Vnode, pObjectInfo->FileId.Unique, stIoSB.Status, stIoSB.Information); ntStatus = stIoSB.Status; } } __except( EXCEPTION_EXECUTE_HANDLER) { ntStatus = GetExceptionCode(); } } // // Uninitialize the cache map. This call is unconditional. // AFSDbgLogMsg( AFS_SUBSYSTEM_IO_PROCESSING, AFS_TRACE_LEVEL_VERBOSE, "AFSCleanup Tearing down cache map for Fcb %08lX FileObject %08lX\n", pFcb, pFileObject); CcUninitializeCacheMap( pFileObject, NULL, NULL); // // Unlock all outstanding locks on the file, again, unconditionally // (VOID) FsRtlFastUnlockAll( &pFcb->Specific.File.FileLock, pFileObject, IoGetRequestorProcess( Irp), NULL); // // Tell the service to unlock all on the file // ulNotificationFlags |= AFS_REQUEST_FLAG_BYTE_RANGE_UNLOCK_ALL; // // Perform some final common processing // ASSERT( pFcb->OpenHandleCount != 0); InterlockedDecrement( &pFcb->OpenHandleCount); AFSDbgLogMsg( AFS_SUBSYSTEM_FCB_REF_COUNTING, AFS_TRACE_LEVEL_VERBOSE, "AFSCleanup (File) Decrement handle count on Fcb %08lX Cnt %d\n", pFcb, pFcb->OpenHandleCount); if( pFcb->ObjectInformation->ParentObjectInformation != NULL) { stFileCleanup.ParentId = pFcb->ObjectInformation->ParentObjectInformation->FileId; } stFileCleanup.LastAccessTime = pObjectInfo->LastAccessTime; if( BooleanFlagOn( pFcb->Flags, AFS_FCB_FLAG_FILE_MODIFIED)) { stFileCleanup.AllocationSize = pObjectInfo->EndOfFile; stFileCleanup.FileAttributes = pObjectInfo->FileAttributes; if( BooleanFlagOn( pFcb->Flags, AFS_FCB_FLAG_UPDATE_CREATE_TIME)) { stFileCleanup.CreateTime = pObjectInfo->CreationTime; ClearFlag( pFcb->Flags, AFS_FCB_FLAG_UPDATE_CREATE_TIME); } if( BooleanFlagOn( pFcb->Flags, AFS_FCB_FLAG_UPDATE_CHANGE_TIME)) { stFileCleanup.ChangeTime = pObjectInfo->ChangeTime; ClearFlag( pFcb->Flags, AFS_FCB_FLAG_UPDATE_CHANGE_TIME); } if( BooleanFlagOn( pFcb->Flags, AFS_FCB_FLAG_UPDATE_ACCESS_TIME)) { stFileCleanup.LastAccessTime = pObjectInfo->LastAccessTime; ClearFlag( pFcb->Flags, AFS_FCB_FLAG_UPDATE_ACCESS_TIME); } if( BooleanFlagOn( pFcb->Flags, AFS_FCB_FLAG_UPDATE_LAST_WRITE_TIME)) { stFileCleanup.LastWriteTime = pObjectInfo->LastWriteTime; ClearFlag( pFcb->Flags, AFS_FCB_FLAG_UPDATE_LAST_WRITE_TIME | AFS_FCB_FLAG_UPDATE_WRITE_TIME); } } if( BooleanFlagOn( pFcb->Flags, AFS_FCB_FLAG_UPDATE_WRITE_TIME)) { stFileCleanup.LastWriteTime = pObjectInfo->LastWriteTime; } // // If the count has dropped to zero and there is a pending delete // then delete the node // if( pFcb->OpenHandleCount == 0 && BooleanFlagOn( pCcb->DirectoryCB->Flags, AFS_DIR_ENTRY_PENDING_DELETE)) { // // Stop anything possibly in process // AFSDbgLogMsg( AFS_SUBSYSTEM_LOCK_PROCESSING, AFS_TRACE_LEVEL_VERBOSE, "AFSCleanup Acquiring Fcb extents lock %08lX EXCL %08lX\n", &pFcb->NPFcb->Specific.File.ExtentsResource, PsGetCurrentThread()); AFSAcquireExcl( &pObjectInfo->Fcb->NPFcb->Specific.File.ExtentsResource, TRUE); pObjectInfo->Fcb->NPFcb->Specific.File.ExtentsRequestStatus = STATUS_FILE_DELETED; KeSetEvent( &pObjectInfo->Fcb->NPFcb->Specific.File.ExtentsRequestComplete, 0, FALSE); AFSDbgLogMsg( AFS_SUBSYSTEM_LOCK_PROCESSING, AFS_TRACE_LEVEL_VERBOSE, "AFSCleanup Releasing Fcb extents lock %08lX EXCL %08lX\n", &pFcb->NPFcb->Specific.File.ExtentsResource, PsGetCurrentThread()); AFSReleaseResource( &pObjectInfo->Fcb->NPFcb->Specific.File.ExtentsResource); // // Before telling the server about the deleted file, tear down all extents for // the file // AFSTearDownFcbExtents( pFcb, &pCcb->AuthGroup); ntStatus = STATUS_SUCCESS; ulNotificationFlags |= AFS_REQUEST_FLAG_FILE_DELETED; // // Indicate the file access mode that is being released // stFileCleanup.FileAccess = pCcb->FileAccess; // // Push the request to the service // ntStatus = AFSProcessRequest( AFS_REQUEST_TYPE_CLEANUP_PROCESSING, ulNotificationFlags | AFS_REQUEST_FLAG_SYNCHRONOUS, &pCcb->AuthGroup, &pCcb->DirectoryCB->NameInformation.FileName, &pObjectInfo->FileId, &stFileCleanup, sizeof( AFSFileCleanupCB), NULL, NULL); if( !NT_SUCCESS( ntStatus) && ntStatus != STATUS_OBJECT_NAME_NOT_FOUND) { AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING, AFS_TRACE_LEVEL_ERROR, "AFSCleanup Failed to notify service of deleted file %wZ Status %08lX\n", &pCcb->FullFileName, ntStatus); ntStatus = STATUS_SUCCESS; ClearFlag( pCcb->DirectoryCB->Flags, AFS_DIR_ENTRY_PENDING_DELETE); } else { ntStatus = STATUS_SUCCESS; AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING, AFS_TRACE_LEVEL_VERBOSE, "AFSCleanup Setting DELETE flag in file %wZ Dir Entry %p\n", &pCcb->FullFileName, pCcb->DirectoryCB); SetFlag( pCcb->DirectoryCB->Flags, AFS_DIR_ENTRY_DELETED); ASSERT( pObjectInfo->ParentObjectInformation != NULL); AFSFsRtlNotifyFullReportChange( pObjectInfo->ParentObjectInformation, pCcb, (ULONG)FILE_NOTIFY_CHANGE_FILE_NAME, (ULONG)FILE_ACTION_REMOVED); // // Now that the service has the entry has deleted we need to remove it from the parent // tree so another lookup on the node will fail // if( !BooleanFlagOn( pCcb->DirectoryCB->Flags, AFS_DIR_ENTRY_NOT_IN_PARENT_TREE)) { AFSAcquireExcl( pObjectInfo->ParentObjectInformation->Specific.Directory.DirectoryNodeHdr.TreeLock, TRUE); AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING, AFS_TRACE_LEVEL_VERBOSE, "AFSCleanup DE %p for %wZ removing entry\n", pCcb->DirectoryCB, &pCcb->DirectoryCB->NameInformation.FileName); AFSRemoveNameEntry( pObjectInfo->ParentObjectInformation, pCcb->DirectoryCB); AFSReleaseResource( pObjectInfo->ParentObjectInformation->Specific.Directory.DirectoryNodeHdr.TreeLock); } else { AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING, AFS_TRACE_LEVEL_VERBOSE, "AFSCleanup DE %p for %wZ NOT removing entry due to flag set\n", pCcb->DirectoryCB, &pCcb->DirectoryCB->NameInformation.FileName); } } } else { if( BooleanFlagOn( pFcb->Flags, AFS_FCB_FLAG_FILE_MODIFIED)) { ULONG ulNotifyFilter = 0; ClearFlag( pFcb->Flags, AFS_FCB_FLAG_FILE_MODIFIED); ulNotifyFilter |= (FILE_NOTIFY_CHANGE_ATTRIBUTES); AFSFsRtlNotifyFullReportChange( pObjectInfo->ParentObjectInformation, pCcb, (ULONG)ulNotifyFilter, (ULONG)FILE_ACTION_MODIFIED); } // // Attempt to flush any dirty extents to the server. This may be a little // aggressive, to flush whenever the handle is closed, but it ensures // coherency. // if( (pCcb->GrantedAccess & FILE_WRITE_DATA) && pFcb->Specific.File.ExtentsDirtyCount != 0) { AFSFlushExtents( pFcb, &pCcb->AuthGroup); } if( pFcb->OpenHandleCount == 0) { // // Wait for any outstanding queued flushes to complete // AFSWaitOnQueuedFlushes( pFcb); ulNotificationFlags |= AFS_REQUEST_FLAG_FLUSH_FILE; } // // Indicate the file access mode that is being released // stFileCleanup.FileAccess = pCcb->FileAccess; // // Push the request to the service // AFSProcessRequest( AFS_REQUEST_TYPE_CLEANUP_PROCESSING, ulNotificationFlags | AFS_REQUEST_FLAG_SYNCHRONOUS, &pCcb->AuthGroup, &pCcb->DirectoryCB->NameInformation.FileName, &pObjectInfo->FileId, &stFileCleanup, sizeof( AFSFileCleanupCB), NULL, NULL); } // // Remove the share access at this time since we may not get the close for sometime on this FO. // IoRemoveShareAccess( pFileObject, &pFcb->ShareAccess); // // We don't need the name array after the user closes the handle on the file // if( pCcb->NameArray != NULL) { AFSFreeNameArray( pCcb->NameArray); pCcb->NameArray = NULL; } // // Decrement the open child handle count // if( pObjectInfo->ParentObjectInformation != NULL) { ASSERT( pObjectInfo->ParentObjectInformation->Specific.Directory.ChildOpenHandleCount > 0); InterlockedDecrement( &pObjectInfo->ParentObjectInformation->Specific.Directory.ChildOpenHandleCount); AFSDbgLogMsg( AFS_SUBSYSTEM_FCB_REF_COUNTING, AFS_TRACE_LEVEL_VERBOSE, "AFSCleanup (File) Decrement child open handle count on Parent object %08lX Cnt %d\n", pObjectInfo->ParentObjectInformation, pObjectInfo->ParentObjectInformation->Specific.Directory.ChildOpenHandleCount); } // // And finally, release the Fcb if we acquired it. // AFSReleaseResource( &pFcb->NPFcb->Resource); break; } // // Root or directory node // case AFS_ROOT_FCB: { // // Set the root Fcb to this node // pRootFcb = pFcb; // // Fall through to below // } case AFS_DIRECTORY_FCB: { // // We may be performing some cleanup on the Fcb so grab it exclusive to ensure no collisions // AFSDbgLogMsg( AFS_SUBSYSTEM_LOCK_PROCESSING, AFS_TRACE_LEVEL_VERBOSE, "AFSCleanup Acquiring Dcb lock %08lX EXCL %08lX\n", &pFcb->NPFcb->Resource, PsGetCurrentThread()); AFSAcquireExcl( &pFcb->NPFcb->Resource, TRUE); // // Perform some final common processing // ASSERT( pFcb->OpenHandleCount != 0); InterlockedDecrement( &pFcb->OpenHandleCount); AFSDbgLogMsg( AFS_SUBSYSTEM_FCB_REF_COUNTING, AFS_TRACE_LEVEL_VERBOSE, "AFSCleanup (Dir) Decrement handle count on Fcb %08lX Cnt %d\n", pFcb, pFcb->OpenHandleCount); if( pFcb->ObjectInformation->ParentObjectInformation != NULL) { stFileCleanup.ParentId = pFcb->ObjectInformation->ParentObjectInformation->FileId; } stFileCleanup.LastAccessTime = pObjectInfo->LastAccessTime; if( BooleanFlagOn( pFcb->Flags, AFS_FCB_FLAG_FILE_MODIFIED)) { stFileCleanup.FileAttributes = pObjectInfo->FileAttributes; if( BooleanFlagOn( pFcb->Flags, AFS_FCB_FLAG_UPDATE_CREATE_TIME)) { stFileCleanup.CreateTime = pObjectInfo->CreationTime; ClearFlag( pFcb->Flags, AFS_FCB_FLAG_UPDATE_CREATE_TIME); } if( BooleanFlagOn( pFcb->Flags, AFS_FCB_FLAG_UPDATE_CHANGE_TIME)) { stFileCleanup.ChangeTime = pObjectInfo->ChangeTime; ClearFlag( pFcb->Flags, AFS_FCB_FLAG_UPDATE_CHANGE_TIME); } if( BooleanFlagOn( pFcb->Flags, AFS_FCB_FLAG_UPDATE_ACCESS_TIME)) { stFileCleanup.LastAccessTime = pObjectInfo->LastAccessTime; ClearFlag( pFcb->Flags, AFS_FCB_FLAG_UPDATE_ACCESS_TIME); } } // // If the count has dropped to zero and there is a pending delete // then delete the node // if( pFcb->OpenHandleCount == 0 && BooleanFlagOn( pCcb->DirectoryCB->Flags, AFS_DIR_ENTRY_PENDING_DELETE)) { // // Try to notify the service about the delete // ulNotificationFlags |= AFS_REQUEST_FLAG_FILE_DELETED; // // Indicate the file access mode that is being released // stFileCleanup.FileAccess = pCcb->FileAccess; // // Push the request to the service // ntStatus = AFSProcessRequest( AFS_REQUEST_TYPE_CLEANUP_PROCESSING, ulNotificationFlags | AFS_REQUEST_FLAG_SYNCHRONOUS, &pCcb->AuthGroup, &pCcb->DirectoryCB->NameInformation.FileName, &pObjectInfo->FileId, &stFileCleanup, sizeof( AFSFileCleanupCB), NULL, NULL); if( !NT_SUCCESS( ntStatus) && ntStatus != STATUS_OBJECT_NAME_NOT_FOUND) { AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING, AFS_TRACE_LEVEL_ERROR, "AFSCleanup Failed to notify service of deleted directory %wZ Status %08lX\n", &pCcb->FullFileName, ntStatus); ntStatus = STATUS_SUCCESS; ClearFlag( pCcb->DirectoryCB->Flags, AFS_DIR_ENTRY_PENDING_DELETE); } else { ntStatus = STATUS_SUCCESS; AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING, AFS_TRACE_LEVEL_VERBOSE, "AFSCleanup Setting DELETE flag in directory %wZ Dir Entry %p\n", &pCcb->FullFileName, pCcb->DirectoryCB); SetFlag( pCcb->DirectoryCB->Flags, AFS_DIR_ENTRY_DELETED); ASSERT( pObjectInfo->ParentObjectInformation != NULL); AFSFsRtlNotifyFullReportChange( pObjectInfo->ParentObjectInformation, pCcb, (ULONG)FILE_NOTIFY_CHANGE_FILE_NAME, (ULONG)FILE_ACTION_REMOVED); // // Now that the service has the entry has deleted we need to remove it from the parent // tree so another lookup on the node will fail // if( !BooleanFlagOn( pCcb->DirectoryCB->Flags, AFS_DIR_ENTRY_NOT_IN_PARENT_TREE)) { AFSAcquireExcl( pObjectInfo->ParentObjectInformation->Specific.Directory.DirectoryNodeHdr.TreeLock, TRUE); AFSRemoveNameEntry( pObjectInfo->ParentObjectInformation, pCcb->DirectoryCB); AFSReleaseResource( pObjectInfo->ParentObjectInformation->Specific.Directory.DirectoryNodeHdr.TreeLock); } else { AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING, AFS_TRACE_LEVEL_VERBOSE, "AFSCleanup DE %p for %wZ NOT removing entry due to flag set\n", pCcb->DirectoryCB, &pCcb->DirectoryCB->NameInformation.FileName); } } } // // If there have been any updates to the node then push it to // the service // else { if( BooleanFlagOn( pFcb->Flags, AFS_FCB_FLAG_FILE_MODIFIED)) { ULONG ulNotifyFilter = 0; ClearFlag( pFcb->Flags, AFS_FCB_FLAG_FILE_MODIFIED); if( pObjectInfo->ParentObjectInformation != NULL) { ulNotifyFilter |= (FILE_NOTIFY_CHANGE_ATTRIBUTES); AFSFsRtlNotifyFullReportChange( pObjectInfo->ParentObjectInformation, pCcb, (ULONG)ulNotifyFilter, (ULONG)FILE_ACTION_MODIFIED); } } // // Indicate the file access mode that is being released // stFileCleanup.FileAccess = pCcb->FileAccess; AFSProcessRequest( AFS_REQUEST_TYPE_CLEANUP_PROCESSING, ulNotificationFlags | AFS_REQUEST_FLAG_SYNCHRONOUS, &pCcb->AuthGroup, &pCcb->DirectoryCB->NameInformation.FileName, &pObjectInfo->FileId, &stFileCleanup, sizeof( AFSFileCleanupCB), NULL, NULL); } // // Release the notification for this directory if there is one // FsRtlNotifyCleanup( pControlDeviceExt->Specific.Control.NotifySync, &pControlDeviceExt->Specific.Control.DirNotifyList, pCcb); // // Remove the share access at this time since we may not get the close for sometime on this FO. // IoRemoveShareAccess( pFileObject, &pFcb->ShareAccess); // // We don't need the name array after the user closes the handle on the file // if( pCcb->NameArray != NULL) { AFSFreeNameArray( pCcb->NameArray); pCcb->NameArray = NULL; } // // Decrement the open child handle count // if( pObjectInfo->ParentObjectInformation != NULL) { ASSERT( pObjectInfo->ParentObjectInformation->Specific.Directory.ChildOpenHandleCount > 0); InterlockedDecrement( &pObjectInfo->ParentObjectInformation->Specific.Directory.ChildOpenHandleCount); AFSDbgLogMsg( AFS_SUBSYSTEM_FCB_REF_COUNTING, AFS_TRACE_LEVEL_VERBOSE, "AFSCleanup (Dir) Decrement child open handle count on Parent object %08lX Cnt %d\n", pObjectInfo->ParentObjectInformation, pObjectInfo->ParentObjectInformation->Specific.Directory.ChildOpenHandleCount); } // // And finally, release the Fcb if we acquired it. // AFSReleaseResource( &pFcb->NPFcb->Resource); break; } case AFS_SYMBOLIC_LINK_FCB: case AFS_MOUNT_POINT_FCB: case AFS_DFS_LINK_FCB: case AFS_INVALID_FCB: { // // We may be performing some cleanup on the Fcb so grab it exclusive to ensure no collisions // AFSDbgLogMsg( AFS_SUBSYSTEM_LOCK_PROCESSING, AFS_TRACE_LEVEL_VERBOSE, "AFSCleanup (MP/SL) Acquiring Dcb lock %08lX EXCL %08lX\n", &pFcb->NPFcb->Resource, PsGetCurrentThread()); AFSAcquireExcl( &pFcb->NPFcb->Resource, TRUE); // // Perform some final common processing // ASSERT( pFcb->OpenHandleCount != 0); InterlockedDecrement( &pFcb->OpenHandleCount); AFSDbgLogMsg( AFS_SUBSYSTEM_FCB_REF_COUNTING, AFS_TRACE_LEVEL_VERBOSE, "AFSCleanup (MP/SL) Decrement handle count on Fcb %08lX Cnt %d\n", pFcb, pFcb->OpenHandleCount); if( pFcb->ObjectInformation->ParentObjectInformation != NULL) { stFileCleanup.ParentId = pFcb->ObjectInformation->ParentObjectInformation->FileId; } stFileCleanup.LastAccessTime = pObjectInfo->LastAccessTime; if( BooleanFlagOn( pFcb->Flags, AFS_FCB_FLAG_FILE_MODIFIED)) { stFileCleanup.FileAttributes = pObjectInfo->FileAttributes; if( BooleanFlagOn( pFcb->Flags, AFS_FCB_FLAG_UPDATE_CREATE_TIME)) { stFileCleanup.CreateTime = pObjectInfo->CreationTime; ClearFlag( pFcb->Flags, AFS_FCB_FLAG_UPDATE_CREATE_TIME); } if( BooleanFlagOn( pFcb->Flags, AFS_FCB_FLAG_UPDATE_CHANGE_TIME)) { stFileCleanup.ChangeTime = pObjectInfo->ChangeTime; ClearFlag( pFcb->Flags, AFS_FCB_FLAG_UPDATE_CHANGE_TIME); } if( BooleanFlagOn( pFcb->Flags, AFS_FCB_FLAG_UPDATE_ACCESS_TIME)) { stFileCleanup.LastAccessTime = pObjectInfo->LastAccessTime; ClearFlag( pFcb->Flags, AFS_FCB_FLAG_UPDATE_ACCESS_TIME); } } // // If the count has dropped to zero and there is a pending delete // then delete the node // if( pFcb->OpenHandleCount == 0 && BooleanFlagOn( pCcb->DirectoryCB->Flags, AFS_DIR_ENTRY_PENDING_DELETE)) { // // Try to notify the service about the delete // ulNotificationFlags |= AFS_REQUEST_FLAG_FILE_DELETED; // // Indicate the file access mode that is being released // stFileCleanup.FileAccess = pCcb->FileAccess; // // Push the request to the service // ntStatus = AFSProcessRequest( AFS_REQUEST_TYPE_CLEANUP_PROCESSING, ulNotificationFlags | AFS_REQUEST_FLAG_SYNCHRONOUS, &pCcb->AuthGroup, &pCcb->DirectoryCB->NameInformation.FileName, &pObjectInfo->FileId, &stFileCleanup, sizeof( AFSFileCleanupCB), NULL, NULL); if( !NT_SUCCESS( ntStatus) && ntStatus != STATUS_OBJECT_NAME_NOT_FOUND) { AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING, AFS_TRACE_LEVEL_ERROR, "AFSCleanup Failed to notify service of deleted MP/SL %wZ Status %08lX\n", &pCcb->FullFileName, ntStatus); ntStatus = STATUS_SUCCESS; ClearFlag( pCcb->DirectoryCB->Flags, AFS_DIR_ENTRY_PENDING_DELETE); } else { ntStatus = STATUS_SUCCESS; AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING, AFS_TRACE_LEVEL_VERBOSE, "AFSCleanup Setting DELETE flag in MP/SL %wZ Dir Entry %p\n", &pCcb->FullFileName, pCcb->DirectoryCB); SetFlag( pCcb->DirectoryCB->Flags, AFS_DIR_ENTRY_DELETED); ASSERT( pObjectInfo->ParentObjectInformation != NULL); AFSFsRtlNotifyFullReportChange( pObjectInfo->ParentObjectInformation, pCcb, (ULONG)FILE_NOTIFY_CHANGE_FILE_NAME, (ULONG)FILE_ACTION_REMOVED); // // Now that the service has the entry has deleted we need to remove it from the parent // tree so another lookup on the node will fail // if( !BooleanFlagOn( pCcb->DirectoryCB->Flags, AFS_DIR_ENTRY_NOT_IN_PARENT_TREE)) { AFSAcquireExcl( pObjectInfo->ParentObjectInformation->Specific.Directory.DirectoryNodeHdr.TreeLock, TRUE); AFSRemoveNameEntry( pObjectInfo->ParentObjectInformation, pCcb->DirectoryCB); AFSReleaseResource( pObjectInfo->ParentObjectInformation->Specific.Directory.DirectoryNodeHdr.TreeLock); } else { AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING, AFS_TRACE_LEVEL_VERBOSE, "AFSCleanup DE %p for %wZ NOT removing entry due to flag set\n", pCcb->DirectoryCB, &pCcb->DirectoryCB->NameInformation.FileName); } } } // // If there have been any updates to the node then push it to // the service // else { if( BooleanFlagOn( pFcb->Flags, AFS_FCB_FLAG_FILE_MODIFIED)) { ULONG ulNotifyFilter = 0; ClearFlag( pFcb->Flags, AFS_FCB_FLAG_FILE_MODIFIED); if( pObjectInfo->ParentObjectInformation != NULL) { ulNotifyFilter |= (FILE_NOTIFY_CHANGE_ATTRIBUTES); AFSFsRtlNotifyFullReportChange( pObjectInfo->ParentObjectInformation, pCcb, (ULONG)ulNotifyFilter, (ULONG)FILE_ACTION_MODIFIED); } } // // Indicate the file access mode that is being released // stFileCleanup.FileAccess = pCcb->FileAccess; AFSProcessRequest( AFS_REQUEST_TYPE_CLEANUP_PROCESSING, ulNotificationFlags | AFS_REQUEST_FLAG_SYNCHRONOUS, &pCcb->AuthGroup, &pCcb->DirectoryCB->NameInformation.FileName, &pObjectInfo->FileId, &stFileCleanup, sizeof( AFSFileCleanupCB), NULL, NULL); } // // Remove the share access at this time since we may not get the close for sometime on this FO. // IoRemoveShareAccess( pFileObject, &pFcb->ShareAccess); // // We don't need the name array after the user closes the handle on the file // if( pCcb->NameArray != NULL) { AFSFreeNameArray( pCcb->NameArray); pCcb->NameArray = NULL; } // // Decrement the open child handle count // if( pObjectInfo->ParentObjectInformation != NULL) { ASSERT( pObjectInfo->ParentObjectInformation->Specific.Directory.ChildOpenHandleCount > 0); InterlockedDecrement( &pObjectInfo->ParentObjectInformation->Specific.Directory.ChildOpenHandleCount); AFSDbgLogMsg( AFS_SUBSYSTEM_FCB_REF_COUNTING, AFS_TRACE_LEVEL_VERBOSE, "AFSCleanup (MP/SL) Decrement child open handle count on Parent object %08lX Cnt %d\n", pObjectInfo->ParentObjectInformation, pObjectInfo->ParentObjectInformation->Specific.Directory.ChildOpenHandleCount); } // // And finally, release the Fcb if we acquired it. // AFSReleaseResource( &pFcb->NPFcb->Resource); break; } case AFS_SPECIAL_SHARE_FCB: { AFSDbgLogMsg( AFS_SUBSYSTEM_LOCK_PROCESSING, AFS_TRACE_LEVEL_VERBOSE, "AFSCleanup Acquiring SPECIAL SHARE lock %08lX EXCL %08lX\n", &pFcb->NPFcb->Resource, PsGetCurrentThread()); AFSAcquireExcl( &pFcb->NPFcb->Resource, TRUE); ASSERT( pFcb->OpenHandleCount != 0); InterlockedDecrement( &pFcb->OpenHandleCount); AFSDbgLogMsg( AFS_SUBSYSTEM_FCB_REF_COUNTING, AFS_TRACE_LEVEL_VERBOSE, "AFSCleanup (Share) Decrement handle count on Fcb %08lX Cnt %d\n", pFcb, pFcb->OpenHandleCount); // // Decrement the open child handle count // if( pObjectInfo->ParentObjectInformation != NULL && pObjectInfo->ParentObjectInformation->Specific.Directory.ChildOpenHandleCount > 0) { InterlockedDecrement( &pObjectInfo->ParentObjectInformation->Specific.Directory.ChildOpenHandleCount); AFSDbgLogMsg( AFS_SUBSYSTEM_FCB_REF_COUNTING, AFS_TRACE_LEVEL_VERBOSE, "AFSCleanup (Share) Decrement child open handle count on Parent object %08lX Cnt %d\n", pObjectInfo->ParentObjectInformation, pObjectInfo->ParentObjectInformation->Specific.Directory.ChildOpenHandleCount); } // // And finally, release the Fcb if we acquired it. // AFSReleaseResource( &pFcb->NPFcb->Resource); break; } default: AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING, AFS_TRACE_LEVEL_WARNING, "AFSCleanup Processing unknown node type %d\n", pFcb->Header.NodeTypeCode); break; } try_exit: if( pFileObject != NULL) { // // Setup the fileobject flags to indicate cleanup is complete. // SetFlag( pFileObject->Flags, FO_CLEANUP_COMPLETE); } // // Complete the request // AFSCompleteRequest( Irp, ntStatus); }
NTSTATUS AFSProcessRequest( IN ULONG RequestType, IN ULONG RequestFlags, IN GUID *AuthGroup, IN PUNICODE_STRING FileName, IN AFSFileID *FileId, IN void *Data, IN ULONG DataLength, IN OUT void *ResultBuffer, IN OUT PULONG ResultBufferLength) { NTSTATUS ntStatus = STATUS_SUCCESS; AFSPoolEntry stPoolEntry, *pPoolEntry = NULL; AFSCommSrvcCB *pCommSrvc = NULL; BOOLEAN bReleasePool = FALSE; AFSDeviceExt *pControlDevExt = (AFSDeviceExt *)AFSDeviceObject->DeviceExtension; AFSDeviceExt *pRDRDevExt = (AFSDeviceExt *)AFSRDRDeviceObject->DeviceExtension; BOOLEAN bWait = BooleanFlagOn( RequestFlags, AFS_REQUEST_FLAG_SYNCHRONOUS); ULONG ulPoolEntryLength = 0; BOOLEAN bDecrementCount = FALSE; __try { if( BooleanFlagOn( pRDRDevExt->DeviceFlags, AFS_DEVICE_FLAG_REDIRECTOR_SHUTDOWN)) { try_return( ntStatus = STATUS_DEVICE_NOT_READY); } if( InterlockedIncrement( &pControlDevExt->Specific.Control.OutstandingServiceRequestCount) == 1) { KeClearEvent( &pControlDevExt->Specific.Control.OutstandingServiceRequestEvent); } bDecrementCount = TRUE; pCommSrvc = &pControlDevExt->Specific.Control.CommServiceCB; // // Grab the pool resource and check the state // AFSDbgLogMsg( AFS_SUBSYSTEM_LOCK_PROCESSING, AFS_TRACE_LEVEL_VERBOSE, "AFSProcessRequest Acquiring IrpPoolLock lock %08lX EXCL %08lX\n", &pCommSrvc->IrpPoolLock, PsGetCurrentThread()); AFSAcquireExcl( &pCommSrvc->IrpPoolLock, TRUE); bReleasePool = TRUE; if( pCommSrvc->IrpPoolControlFlag != POOL_ACTIVE) { // // Pool not running so bail. // try_return( ntStatus = STATUS_DEVICE_NOT_READY); } // // If this is an async request we need to allocate a pool entry for the request // pPoolEntry = &stPoolEntry; if( !bWait) { ASSERT( ResultBuffer == NULL); ulPoolEntryLength = sizeof( AFSPoolEntry) + QuadAlign( DataLength); if( FileName != NULL) { ulPoolEntryLength += FileName->Length; } pPoolEntry = (AFSPoolEntry *)AFSExAllocatePoolWithTag( NonPagedPool, ulPoolEntryLength, AFS_POOL_ENTRY_TAG); if( pPoolEntry == NULL) { try_return( ntStatus = STATUS_INSUFFICIENT_RESOURCES); } RtlZeroMemory( pPoolEntry, ulPoolEntryLength); pPoolEntry->Data = (void *)((char *)pPoolEntry + sizeof( AFSPoolEntry)); pPoolEntry->FileName.Buffer = (WCHAR *)((char *)pPoolEntry->Data + DataLength); } else { RtlZeroMemory( pPoolEntry, sizeof( AFSPoolEntry)); KeInitializeEvent( &pPoolEntry->Event, NotificationEvent, FALSE); } pPoolEntry->RequestType = RequestType; pPoolEntry->RequestIndex = pCommSrvc->IrpPoolRequestIndex++; pPoolEntry->RequestFlags = RequestFlags; pPoolEntry->ResultBufferLength = 0; if( FileId != NULL) { pPoolEntry->FileId = *FileId; } pPoolEntry->FileName.Length = 0; if( FileName != NULL) { if( bWait) { pPoolEntry->FileName = *FileName; } else { pPoolEntry->FileName.Length = FileName->Length; pPoolEntry->FileName.MaximumLength = pPoolEntry->FileName.Length; RtlCopyMemory( pPoolEntry->FileName.Buffer, FileName->Buffer, pPoolEntry->FileName.Length); } } // // Move in the data if there is some // pPoolEntry->DataLength = DataLength; if( Data != NULL && DataLength > 0) { if( bWait) { pPoolEntry->Data = Data; } else { RtlCopyMemory( pPoolEntry->Data, Data, DataLength); } } pPoolEntry->ResultBuffer = ResultBuffer; pPoolEntry->ResultBufferLength = ResultBufferLength; // // Store off the auth group // if( AuthGroup == NULL) { AFSRetrieveAuthGroup( (ULONGLONG)PsGetCurrentProcessId(), (ULONGLONG)PsGetCurrentThreadId(), &pPoolEntry->AuthGroup); } else { RtlCopyMemory( &pPoolEntry->AuthGroup, AuthGroup, sizeof( GUID)); } if( AFSIsLocalSystemAuthGroup( &pPoolEntry->AuthGroup)) { SetFlag( pPoolEntry->RequestFlags, AFS_REQUEST_LOCAL_SYSTEM_PAG); } if( AFSIsNoPAGAuthGroup( &pPoolEntry->AuthGroup)) { AFSDbgLogMsg( 0, 0, "AFSProcessRequest NoPAG Auth Group %08lX\n", PsGetCurrentThread()); } // // Indicate the type of process // #ifdef AMD64 if( !AFSIs64BitProcess( (ULONGLONG)PsGetCurrentProcessId())) { SetFlag( pPoolEntry->RequestFlags, AFS_REQUEST_FLAG_WOW64); } #endif // // Insert the entry into the request pool // ntStatus = AFSInsertRequest( pCommSrvc, pPoolEntry); if( !NT_SUCCESS( ntStatus)) { if( !bWait) { ExFreePool( pPoolEntry); } try_return( ntStatus); } // // Drop the lock on the pool prior to waiting // AFSReleaseResource( &pCommSrvc->IrpPoolLock); bReleasePool = FALSE; // // Wait for the result if this is NOT an asynchronous request // if( bWait) { // // Wait for the result of the request. We specify no timeout ... // ntStatus = KeWaitForSingleObject( &pPoolEntry->Event, Executive, KernelMode, FALSE, NULL); // // Process the result of the request // if( ntStatus == STATUS_SUCCESS) { ntStatus = pPoolEntry->ResultStatus; } else { ntStatus = STATUS_DEVICE_NOT_READY; } } try_exit: if( bReleasePool) { AFSReleaseResource( &pCommSrvc->IrpPoolLock); } if( bDecrementCount && InterlockedDecrement( &pControlDevExt->Specific.Control.OutstandingServiceRequestCount) == 0) { KeSetEvent( &pControlDevExt->Specific.Control.OutstandingServiceRequestEvent, 0, FALSE); } } __except( AFSExceptionFilter( __FUNCTION__, GetExceptionCode(), GetExceptionInformation())) { AFSDumpTraceFilesFnc(); if( bReleasePool) { AFSReleaseResource( &pCommSrvc->IrpPoolLock); } if( bDecrementCount && InterlockedDecrement( &pControlDevExt->Specific.Control.OutstandingServiceRequestCount) == 0) { KeSetEvent( &pControlDevExt->Specific.Control.OutstandingServiceRequestEvent, 0, FALSE); } if ( ntStatus == STATUS_SUCCESS) { ntStatus = STATUS_UNSUCCESSFUL; } } return ntStatus; }
NTSTATUS AFSInitRDRDevice() { NTSTATUS ntStatus = STATUS_SUCCESS; UNICODE_STRING uniDeviceName; ULONG ulIndex = 0; AFSDeviceExt *pDeviceExt = NULL; AFSFileID stRootFid; UNICODE_STRING uniFsRtlRegisterUncProviderEx; FsRtlRegisterUncProviderEx_t pFsRtlRegisterUncProviderEx = NULL; __Enter { RtlInitUnicodeString( &uniDeviceName, AFS_RDR_DEVICE_NAME); RtlInitUnicodeString( &uniFsRtlRegisterUncProviderEx, L"FsRtlRegisterUncProviderEx"); pFsRtlRegisterUncProviderEx = (FsRtlRegisterUncProviderEx_t)MmGetSystemRoutineAddress(&uniFsRtlRegisterUncProviderEx); ntStatus = IoCreateDevice( AFSDriverObject, sizeof( AFSDeviceExt), pFsRtlRegisterUncProviderEx ? NULL : &uniDeviceName, FILE_DEVICE_NETWORK_FILE_SYSTEM, FILE_REMOTE_DEVICE, FALSE, &AFSRDRDeviceObject); if( !NT_SUCCESS( ntStatus)) { AFSDbgLogMsg( AFS_SUBSYSTEM_INIT_PROCESSING, AFS_TRACE_LEVEL_ERROR, "AFSInitRDRDevice IoCreateDevice failure %08lX\n", ntStatus); try_return( ntStatus); } pDeviceExt = (AFSDeviceExt *)AFSRDRDeviceObject->DeviceExtension; RtlZeroMemory( pDeviceExt, sizeof( AFSDeviceExt)); // // Initialize resources // pDeviceExt->Specific.RDR.VolumeTree.TreeLock = &pDeviceExt->Specific.RDR.VolumeTreeLock; ExInitializeResourceLite( pDeviceExt->Specific.RDR.VolumeTree.TreeLock); pDeviceExt->Specific.RDR.VolumeTree.TreeHead = NULL; ExInitializeResourceLite( &pDeviceExt->Specific.RDR.VolumeListLock); pDeviceExt->Specific.RDR.VolumeListHead = NULL; pDeviceExt->Specific.RDR.VolumeListTail = NULL; KeInitializeEvent( &pDeviceExt->Specific.RDR.QueuedReleaseExtentEvent, NotificationEvent, TRUE); ExInitializeResourceLite( &pDeviceExt->Specific.RDR.RootCellTreeLock); pDeviceExt->Specific.RDR.RootCellTree.TreeLock = &pDeviceExt->Specific.RDR.RootCellTreeLock; pDeviceExt->Specific.RDR.RootCellTree.TreeHead = NULL; ExInitializeResourceLite( &pDeviceExt->Specific.RDR.ProviderListLock); // // Clear the initializing bit // AFSRDRDeviceObject->Flags &= ~DO_DEVICE_INITIALIZING; // // Register this device with MUP with FilterMgr if Vista or above // if( pFsRtlRegisterUncProviderEx) { ntStatus = pFsRtlRegisterUncProviderEx( &AFSMUPHandle, &uniDeviceName, AFSRDRDeviceObject, 0); if ( !NT_SUCCESS( ntStatus)) { AFSDbgLogMsg( AFS_SUBSYSTEM_INIT_PROCESSING, AFS_TRACE_LEVEL_ERROR, "AFSInitRDRDevice FsRtlRegisterUncProvider failure %08lX\n", ntStatus); } } else { ntStatus = FsRtlRegisterUncProvider( &AFSMUPHandle, &uniDeviceName, FALSE); if ( NT_SUCCESS( ntStatus)) { IoRegisterFileSystem( AFSRDRDeviceObject); } else { AFSDbgLogMsg( AFS_SUBSYSTEM_INIT_PROCESSING, AFS_TRACE_LEVEL_ERROR, "AFSInitRDRDevice FsRtlRegisterUncProvider failure %08lX\n", ntStatus); } } if( !NT_SUCCESS( ntStatus)) { // // Delete our device and bail // ExDeleteResourceLite( pDeviceExt->Specific.RDR.VolumeTree.TreeLock); ExDeleteResourceLite( &pDeviceExt->Specific.RDR.VolumeListLock); ExDeleteResourceLite( &pDeviceExt->Specific.RDR.RootCellTreeLock); ExDeleteResourceLite( &pDeviceExt->Specific.RDR.ProviderListLock); IoDeleteDevice( AFSRDRDeviceObject); AFSRDRDeviceObject = NULL; try_return( ntStatus); } // // Good to go, all registered and ready to start receiving requests // try_exit: if( !NT_SUCCESS( ntStatus)) { } } return ntStatus; }
NTSTATUS AFSInitFcb( IN AFSDirectoryCB *DirEntry, IN OUT AFSFcb **Fcb) { NTSTATUS ntStatus = STATUS_SUCCESS; AFSDeviceExt *pDeviceExt = (AFSDeviceExt *)AFSRDRDeviceObject->DeviceExtension; AFSFcb *pFcb = NULL; AFSNonPagedFcb *pNPFcb = NULL; IO_STATUS_BLOCK stIoSb = {0,0}; BOOLEAN bUninitFileLock = FALSE; USHORT usFcbLength = 0; ULONGLONG ullIndex = 0; AFSDirEnumEntry *pDirEnumCB = NULL; AFSObjectInfoCB *pObjectInfo = NULL, *pParentObjectInfo = NULL; AFSVolumeCB *pVolumeCB = NULL; __Enter { pObjectInfo = DirEntry->ObjectInformation; pParentObjectInfo = pObjectInfo->ParentObjectInformation; pVolumeCB = pObjectInfo->VolumeCB; // // Allocate the Fcb and the nonpaged portion of the Fcb. // AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING, AFS_TRACE_LEVEL_VERBOSE_2, "AFSInitFcb Initializing fcb for %wZ FID %08lX-%08lX-%08lX-%08lX\n", &DirEntry->NameInformation.FileName, pObjectInfo->FileId.Cell, pObjectInfo->FileId.Volume, pObjectInfo->FileId.Vnode, pObjectInfo->FileId.Unique); usFcbLength = sizeof( AFSFcb); pFcb = (AFSFcb *)AFSExAllocatePoolWithTag( PagedPool, usFcbLength, AFS_FCB_ALLOCATION_TAG); if( pFcb == NULL) { AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING, AFS_TRACE_LEVEL_ERROR, "AFSInitFcb Failed to allocate fcb\n"); try_return( ntStatus = STATUS_INSUFFICIENT_RESOURCES); } RtlZeroMemory( pFcb, usFcbLength); pFcb->Header.NodeByteSize = usFcbLength; pNPFcb = (AFSNonPagedFcb *)AFSExAllocatePoolWithTag( NonPagedPool, sizeof( AFSNonPagedFcb), AFS_FCB_NP_ALLOCATION_TAG); if( pNPFcb == NULL) { AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING, AFS_TRACE_LEVEL_ERROR, "AFSInitFcb Failed to allocate non-paged fcb\n"); try_return( ntStatus = STATUS_INSUFFICIENT_RESOURCES); } RtlZeroMemory( pNPFcb, sizeof( AFSNonPagedFcb)); pNPFcb->Size = sizeof( AFSNonPagedFcb); pNPFcb->Type = AFS_NON_PAGED_FCB; // // Initialize the advanced header // ExInitializeFastMutex( &pNPFcb->AdvancedHdrMutex); FsRtlSetupAdvancedHeader( &pFcb->Header, &pNPFcb->AdvancedHdrMutex); // // OK, initialize the entry // ExInitializeResourceLite( &pNPFcb->Resource); ExInitializeResourceLite( &pNPFcb->PagingResource); ExInitializeResourceLite( &pNPFcb->CcbListLock); pFcb->Header.Resource = &pNPFcb->Resource; pFcb->Header.PagingIoResource = &pNPFcb->PagingResource; // // Grab the Fcb for processing // AFSDbgLogMsg( AFS_SUBSYSTEM_LOCK_PROCESSING, AFS_TRACE_LEVEL_VERBOSE, "AFSInitFcb Acquiring Fcb lock %08lX EXCL %08lX\n", &pNPFcb->Resource, PsGetCurrentThread()); AFSAcquireExcl( &pNPFcb->Resource, TRUE); pFcb->NPFcb = pNPFcb; // // Initialize some fields in the Fcb // pFcb->ObjectInformation = pObjectInfo; pObjectInfo->Fcb = pFcb; // // Set type specific information // if( pObjectInfo->FileType == AFS_FILE_TYPE_DIRECTORY) { // // Reset the type to a directory type // pFcb->Header.NodeTypeCode = AFS_DIRECTORY_FCB; // // Initialize enumeration information // KeInitializeEvent( &pFcb->NPFcb->Specific.Directory.DirectoryEnumEvent, NotificationEvent, FALSE); } else if( pObjectInfo->FileType == AFS_FILE_TYPE_FILE) { pFcb->Header.NodeTypeCode = AFS_FILE_FCB; // // Initialize the file specific information // FsRtlInitializeFileLock( &pFcb->Specific.File.FileLock, NULL, NULL); bUninitFileLock = TRUE; // // Initialize the header file sizes to our dir entry information // pFcb->Header.AllocationSize.QuadPart = pObjectInfo->AllocationSize.QuadPart; pFcb->Header.FileSize.QuadPart = pObjectInfo->EndOfFile.QuadPart; pFcb->Header.ValidDataLength.QuadPart = pObjectInfo->EndOfFile.QuadPart; // // Initialize the Extents resources and so forth. The // quiescent state is that no one has the extents for // IO (do the extents are not busy) and there is no // extents request outstanding (and hence the "last // one" is complete). // ExInitializeResourceLite( &pNPFcb->Specific.File.ExtentsResource ); KeInitializeEvent( &pNPFcb->Specific.File.ExtentsRequestComplete, NotificationEvent, TRUE ); for (ULONG i = 0; i < AFS_NUM_EXTENT_LISTS; i++) { InitializeListHead(&pFcb->Specific.File.ExtentsLists[i]); } pNPFcb->Specific.File.DirtyListHead = NULL; pNPFcb->Specific.File.DirtyListTail = NULL; ExInitializeResourceLite( &pNPFcb->Specific.File.DirtyExtentsListLock); KeInitializeEvent( &pNPFcb->Specific.File.FlushEvent, SynchronizationEvent, TRUE); KeInitializeEvent( &pNPFcb->Specific.File.QueuedFlushEvent, NotificationEvent, TRUE); } else if( pObjectInfo->FileType == AFS_FILE_TYPE_SPECIAL_SHARE_NAME) { pFcb->Header.NodeTypeCode = AFS_SPECIAL_SHARE_FCB; } else if( pObjectInfo->FileType == AFS_FILE_TYPE_PIOCTL) { pFcb->Header.NodeTypeCode = AFS_IOCTL_FCB; } else if( pObjectInfo->FileType == AFS_FILE_TYPE_SYMLINK) { pFcb->Header.NodeTypeCode = AFS_SYMBOLIC_LINK_FCB; } else if( pObjectInfo->FileType == AFS_FILE_TYPE_MOUNTPOINT) { pFcb->Header.NodeTypeCode = AFS_MOUNT_POINT_FCB; } else if( pObjectInfo->FileType == AFS_FILE_TYPE_DFSLINK) { pFcb->Header.NodeTypeCode = AFS_DFS_LINK_FCB; } else { pFcb->Header.NodeTypeCode = AFS_INVALID_FCB; } // // And return the Fcb // *Fcb = pFcb; AFSDbgLogMsg( AFS_SUBSYSTEM_FCB_REF_COUNTING, AFS_TRACE_LEVEL_VERBOSE, "AFSInitFcb Initialized Fcb %08lX Name %wZ\n", pFcb, &DirEntry->NameInformation.FileName); try_exit: if( !NT_SUCCESS( ntStatus)) { AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING, AFS_TRACE_LEVEL_ERROR, "AFSInitFcb Failed to initialize fcb Status %08lX\n", ntStatus); if( pFcb != NULL) { if( bUninitFileLock) { FsRtlUninitializeFileLock( &pFcb->Specific.File.FileLock); } if( pNPFcb != NULL) { AFSReleaseResource( &pNPFcb->Resource); ExDeleteResourceLite( &pNPFcb->PagingResource); ExDeleteResourceLite( &pNPFcb->CcbListLock); ExDeleteResourceLite( &pNPFcb->Resource); } AFSExFreePool( pFcb); } if( pNPFcb != NULL) { AFSExFreePool( pNPFcb); } if( Fcb != NULL) { *Fcb = NULL; } } } return ntStatus; }
NTSTATUS AFSClose( IN PDEVICE_OBJECT LibDeviceObject, IN PIRP Irp) { NTSTATUS ntStatus = STATUS_SUCCESS; ULONG ulRequestType = 0; IO_STACK_LOCATION *pIrpSp = IoGetCurrentIrpStackLocation( Irp); AFSFcb *pFcb = NULL; AFSDeviceExt *pDeviceExt = NULL; AFSCcb *pCcb = NULL; AFSObjectInfoCB *pObjectInfo = NULL; AFSDirectoryCB *pDirCB = NULL; __try { if( AFSRDRDeviceObject == NULL) { // // Let this through, it's an close on the library control device // try_return( ntStatus); } pDeviceExt = (AFSDeviceExt *)AFSRDRDeviceObject->DeviceExtension; pIrpSp = IoGetCurrentIrpStackLocation( Irp); pFcb = (AFSFcb *)pIrpSp->FileObject->FsContext; if( pFcb == NULL) { try_return( ntStatus); } pObjectInfo = pFcb->ObjectInformation; // // Perform the close functionality depending on the type of node it is // switch( pFcb->Header.NodeTypeCode) { case AFS_IOCTL_FCB: { AFSPIOCtlOpenCloseRequestCB stPIOCtlClose; AFSFileID stParentFileId; AFSDbgLogMsg( AFS_SUBSYSTEM_LOCK_PROCESSING, AFS_TRACE_LEVEL_VERBOSE, "AFSClose Acquiring GlobalRoot lock %08lX EXCL %08lX\n", &pFcb->NPFcb->Resource, PsGetCurrentThread()); AFSAcquireExcl( &pFcb->NPFcb->Resource, TRUE); pCcb = (AFSCcb *)pIrpSp->FileObject->FsContext2; // // Send the close to the CM // RtlZeroMemory( &stPIOCtlClose, sizeof( AFSPIOCtlOpenCloseRequestCB)); stPIOCtlClose.RequestId = pCcb->RequestID; stPIOCtlClose.RootId = pObjectInfo->VolumeCB->ObjectInformation.FileId; RtlZeroMemory( &stParentFileId, sizeof( AFSFileID)); stParentFileId = pObjectInfo->ParentObjectInformation->FileId; // // Issue the close request to the service // AFSProcessRequest( AFS_REQUEST_TYPE_PIOCTL_CLOSE, AFS_REQUEST_FLAG_SYNCHRONOUS, &pCcb->AuthGroup, NULL, &stParentFileId, (void *)&stPIOCtlClose, sizeof( AFSPIOCtlOpenCloseRequestCB), NULL, NULL); pDirCB = pCcb->DirectoryCB; // // Remove the Ccb and de-allocate it // ntStatus = AFSRemoveCcb( pFcb, pCcb); if( !NT_SUCCESS( ntStatus)) { AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING, AFS_TRACE_LEVEL_WARNING, "AFSClose Failed to remove Ccb from Fcb Status %08lX\n", ntStatus); // // We can't actually fail a close operation so reset the status // ntStatus = STATUS_SUCCESS; } ASSERT( pDirCB->OpenReferenceCount > 0); InterlockedDecrement( &pDirCB->OpenReferenceCount); AFSDbgLogMsg( AFS_SUBSYSTEM_DIRENTRY_REF_COUNTING, AFS_TRACE_LEVEL_VERBOSE, "AFSClose (IOCtl) Decrement count on %wZ DE %p Ccb %p Cnt %d\n", &pDirCB->NameInformation.FileName, pDirCB, pCcb, pDirCB->OpenReferenceCount); // // If this is not the root then decrement the open child reference count // if( pObjectInfo->ParentObjectInformation != NULL && pObjectInfo->ParentObjectInformation->Specific.Directory.ChildOpenReferenceCount > 0) { InterlockedDecrement( &pObjectInfo->ParentObjectInformation->Specific.Directory.ChildOpenReferenceCount); AFSDbgLogMsg( AFS_SUBSYSTEM_FCB_REF_COUNTING, AFS_TRACE_LEVEL_VERBOSE, "AFSClose (IOCtl) Decrement child open ref count on Parent object %08lX Cnt %d\n", pObjectInfo->ParentObjectInformation, pObjectInfo->ParentObjectInformation->Specific.Directory.ChildOpenReferenceCount); } AFSReleaseResource( &pFcb->NPFcb->Resource); ASSERT( pFcb->OpenReferenceCount != 0); InterlockedDecrement( &pFcb->OpenReferenceCount); AFSDbgLogMsg( AFS_SUBSYSTEM_FCB_REF_COUNTING, AFS_TRACE_LEVEL_VERBOSE, "AFSClose (IOCtl) Decrement count on Fcb %08lX Cnt %d\n", pFcb, pFcb->OpenReferenceCount); break; } case AFS_ROOT_ALL: { AFSDbgLogMsg( AFS_SUBSYSTEM_LOCK_PROCESSING, AFS_TRACE_LEVEL_VERBOSE, "AFSClose Acquiring Special Root ALL lock %08lX EXCL %08lX\n", &pFcb->NPFcb->Resource, PsGetCurrentThread()); AFSAcquireExcl( &pFcb->NPFcb->Resource, TRUE); pCcb = (AFSCcb *)pIrpSp->FileObject->FsContext2; pDirCB = pCcb->DirectoryCB; // // Remove the Ccb and de-allocate it // ntStatus = AFSRemoveCcb( pFcb, pCcb); if( !NT_SUCCESS( ntStatus)) { AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING, AFS_TRACE_LEVEL_WARNING, "AFSClose Failed to remove Ccb from Fcb Status %08lX\n", ntStatus); // // We can't actually fail a close operation so reset the status // ntStatus = STATUS_SUCCESS; } ASSERT( pDirCB->OpenReferenceCount > 0); InterlockedDecrement( &pDirCB->OpenReferenceCount); AFSDbgLogMsg( AFS_SUBSYSTEM_DIRENTRY_REF_COUNTING, AFS_TRACE_LEVEL_VERBOSE, "AFSClose Decrement (Root ALL) count on %wZ DE %p Ccb %p Cnt %d\n", &pDirCB->NameInformation.FileName, pDirCB, pCcb, pDirCB->OpenReferenceCount); AFSReleaseResource( &pFcb->NPFcb->Resource); ASSERT( pFcb->OpenReferenceCount > 0); InterlockedDecrement( &pFcb->OpenReferenceCount); AFSDbgLogMsg( AFS_SUBSYSTEM_FCB_REF_COUNTING, AFS_TRACE_LEVEL_VERBOSE, "AFSClose (RootAll) Decrement count on Fcb %08lX Cnt %d\n", pFcb, pFcb->OpenReferenceCount); break; } // // Root, file or directory node // case AFS_FILE_FCB: case AFS_ROOT_FCB: case AFS_DIRECTORY_FCB: case AFS_SYMBOLIC_LINK_FCB: case AFS_MOUNT_POINT_FCB: case AFS_DFS_LINK_FCB: case AFS_INVALID_FCB: { pCcb = (AFSCcb *)pIrpSp->FileObject->FsContext2; // // We may be performing some cleanup on the Fcb so grab it exclusive to ensure no collisions // AFSDbgLogMsg( AFS_SUBSYSTEM_LOCK_PROCESSING, AFS_TRACE_LEVEL_VERBOSE, "AFSClose Acquiring Dcb lock %08lX EXCL %08lX\n", &pFcb->NPFcb->Resource, PsGetCurrentThread()); AFSAcquireExcl( &pFcb->NPFcb->Resource, TRUE); KeQueryTickCount( &pFcb->ObjectInformation->LastAccessCount); pDirCB = pCcb->DirectoryCB; // // If this entry is deleted then remove the object from the volume tree // if( BooleanFlagOn( pDirCB->Flags, AFS_DIR_ENTRY_DELETED)) { if( pFcb->Header.NodeTypeCode == AFS_FILE_FCB) { // // Stop anything possibly in process // AFSDbgLogMsg( AFS_SUBSYSTEM_LOCK_PROCESSING, AFS_TRACE_LEVEL_VERBOSE, "AFSClose Acquiring Fcb extents lock %08lX EXCL %08lX\n", &pFcb->NPFcb->Specific.File.ExtentsResource, PsGetCurrentThread()); AFSAcquireExcl( &pObjectInfo->Fcb->NPFcb->Specific.File.ExtentsResource, TRUE); pObjectInfo->Fcb->NPFcb->Specific.File.ExtentsRequestStatus = STATUS_FILE_DELETED; KeSetEvent( &pObjectInfo->Fcb->NPFcb->Specific.File.ExtentsRequestComplete, 0, FALSE); AFSDbgLogMsg( AFS_SUBSYSTEM_LOCK_PROCESSING, AFS_TRACE_LEVEL_VERBOSE, "AFSClose Releasing Fcb extents lock %08lX EXCL %08lX\n", &pFcb->NPFcb->Specific.File.ExtentsResource, PsGetCurrentThread()); AFSReleaseResource( &pObjectInfo->Fcb->NPFcb->Specific.File.ExtentsResource); } AFSAcquireExcl( pObjectInfo->ParentObjectInformation->Specific.Directory.DirectoryNodeHdr.TreeLock, TRUE); AFSAcquireExcl( pObjectInfo->VolumeCB->ObjectInfoTree.TreeLock, TRUE); if ( pDirCB->OpenReferenceCount == 0) { AFSDbgLogMsg( 0, 0, "AFSClose (Other) OpenReferenceCount is Zero on DE %08lX Ccb %08lX FileName %wZ\n", pDirCB, pCcb, &pDirCB->NameInformation.FileName); } ASSERT( pDirCB->OpenReferenceCount > 0); InterlockedDecrement( &pDirCB->OpenReferenceCount); AFSDbgLogMsg( AFS_SUBSYSTEM_DIRENTRY_REF_COUNTING, AFS_TRACE_LEVEL_VERBOSE, "AFSClose (Other) Decrement count on %wZ DE %p Ccb %p Cnt %d\n", &pDirCB->NameInformation.FileName, pDirCB, pCcb, pDirCB->OpenReferenceCount); if( pDirCB->OpenReferenceCount == 0) { AFSDbgLogMsg( AFS_SUBSYSTEM_CLEANUP_PROCESSING, AFS_TRACE_LEVEL_VERBOSE, "AFSClose Deleting dir entry %08lX (%08lX) for %wZ FID %08lX-%08lX-%08lX-%08lX\n", pDirCB, pObjectInfo, &pDirCB->NameInformation.FileName, pObjectInfo->FileId.Cell, pObjectInfo->FileId.Volume, pObjectInfo->FileId.Vnode, pObjectInfo->FileId.Unique); // // Remove and delete the directory entry from the parent list // AFSDeleteDirEntry( pObjectInfo->ParentObjectInformation, pDirCB); if( pObjectInfo->ObjectReferenceCount <= 0) { if( BooleanFlagOn( pObjectInfo->Flags, AFS_OBJECT_INSERTED_HASH_TREE)) { AFSDbgLogMsg( AFS_SUBSYSTEM_CLEANUP_PROCESSING, AFS_TRACE_LEVEL_VERBOSE, "AFSClose Removing object %08lX from volume tree\n", pObjectInfo); AFSRemoveHashEntry( &pObjectInfo->VolumeCB->ObjectInfoTree.TreeHead, &pObjectInfo->TreeEntry); ClearFlag( pObjectInfo->Flags, AFS_OBJECT_INSERTED_HASH_TREE); } SetFlag( pObjectInfo->Flags, AFS_OBJECT_FLAGS_DELETED); } } AFSReleaseResource( pObjectInfo->ParentObjectInformation->Specific.Directory.DirectoryNodeHdr.TreeLock); AFSReleaseResource( pObjectInfo->VolumeCB->ObjectInfoTree.TreeLock); } else { ASSERT( pDirCB->OpenReferenceCount > 0); InterlockedDecrement( &pDirCB->OpenReferenceCount); AFSDbgLogMsg( AFS_SUBSYSTEM_DIRENTRY_REF_COUNTING, AFS_TRACE_LEVEL_VERBOSE, "AFSClose (Other2) Decrement count on %wZ DE %p Ccb %p Cnt %d\n", &pDirCB->NameInformation.FileName, pDirCB, pCcb, pDirCB->OpenReferenceCount); } // // If this is not the root then decrement the open child reference count // if( pObjectInfo != NULL && pObjectInfo->ParentObjectInformation != NULL && pObjectInfo->ParentObjectInformation->Specific.Directory.ChildOpenReferenceCount > 0) { InterlockedDecrement( &pObjectInfo->ParentObjectInformation->Specific.Directory.ChildOpenReferenceCount); AFSDbgLogMsg( AFS_SUBSYSTEM_FCB_REF_COUNTING, AFS_TRACE_LEVEL_VERBOSE, "AFSClose Decrement child open ref count on Parent object %08lX Cnt %d\n", pObjectInfo->ParentObjectInformation, pObjectInfo->ParentObjectInformation->Specific.Directory.ChildOpenReferenceCount); } if( pFcb->OpenReferenceCount == 1 && pFcb->Header.NodeTypeCode == AFS_FILE_FCB) { SetFlag( pFcb->Flags, AFS_FCB_FILE_CLOSED); // // Attempt to tear down our extent list for the file // If there are remaining dirty extents then attempt to // flush them as well // if( pFcb->Specific.File.ExtentsDirtyCount) { AFSFlushExtents( pFcb, &pCcb->AuthGroup); } // // Wait for any outstanding queued flushes to complete // AFSWaitOnQueuedFlushes( pFcb); ASSERT( pFcb->Specific.File.ExtentsDirtyCount == 0 && pFcb->Specific.File.QueuedFlushCount == 0); AFSReleaseResource( &pFcb->NPFcb->Resource); // // Tear 'em down, we'll not be needing them again // AFSTearDownFcbExtents( pFcb, &pCcb->AuthGroup); } else { if( pFcb->Header.NodeTypeCode == AFS_FILE_FCB && pFcb->Specific.File.ExtentsDirtyCount && (pCcb->GrantedAccess & FILE_WRITE_DATA)) { AFSFlushExtents( pFcb, &pCcb->AuthGroup); } AFSReleaseResource( &pFcb->NPFcb->Resource); } // // Remove the Ccb and de-allocate it // ntStatus = AFSRemoveCcb( pFcb, pCcb); if( !NT_SUCCESS( ntStatus)) { AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING, AFS_TRACE_LEVEL_WARNING, "AFSClose Failed to remove Ccb from Fcb Status %08lX\n", ntStatus); // // We can't actually fail a close operation so reset the status // ntStatus = STATUS_SUCCESS; } // // Decrement the reference count on the Fcb. this is protecting it from teardown. // ASSERT( pFcb->OpenReferenceCount != 0); InterlockedDecrement( &pFcb->OpenReferenceCount); AFSDbgLogMsg( AFS_SUBSYSTEM_FCB_REF_COUNTING, AFS_TRACE_LEVEL_VERBOSE, "AFSClose Decrement count on Fcb %08lX Cnt %d\n", pFcb, pFcb->OpenReferenceCount); break; } case AFS_SPECIAL_SHARE_FCB: { AFSPipeOpenCloseRequestCB stPipeClose; AFSDbgLogMsg( AFS_SUBSYSTEM_LOCK_PROCESSING, AFS_TRACE_LEVEL_VERBOSE, "AFSClose Acquiring Special Share lock %08lX EXCL %08lX\n", &pFcb->NPFcb->Resource, PsGetCurrentThread()); AFSAcquireExcl( &pFcb->NPFcb->Resource, TRUE); pCcb = (AFSCcb *)pIrpSp->FileObject->FsContext2; pDirCB = pCcb->DirectoryCB; RtlZeroMemory( &stPipeClose, sizeof( AFSPipeOpenCloseRequestCB)); stPipeClose.RequestId = pCcb->RequestID; stPipeClose.RootId = pObjectInfo->VolumeCB->ObjectInformation.FileId; // // Issue the open request to the service // /* AFSProcessRequest( AFS_REQUEST_TYPE_PIPE_CLOSE, AFS_REQUEST_FLAG_SYNCHRONOUS, &pFcb->AuthGroup, &pDirCB->NameInformation.FileName, NULL, (void *)&stPipeClose, sizeof( AFSPipeOpenCloseRequestCB), NULL, NULL); */ // // Remove the Ccb and de-allocate it // ntStatus = AFSRemoveCcb( pFcb, pCcb); if( !NT_SUCCESS( ntStatus)) { AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING, AFS_TRACE_LEVEL_WARNING, "AFSClose Failed to remove Ccb from Fcb Status %08lX\n", ntStatus); // // We can't actually fail a close operation so reset the status // ntStatus = STATUS_SUCCESS; } ASSERT( pDirCB->OpenReferenceCount > 0); InterlockedDecrement( &pDirCB->OpenReferenceCount); AFSDbgLogMsg( AFS_SUBSYSTEM_DIRENTRY_REF_COUNTING, AFS_TRACE_LEVEL_VERBOSE, "AFSClose (Share) Decrement count on %wZ DE %p Ccb %p Cnt %d\n", &pDirCB->NameInformation.FileName, pDirCB, pCcb, pDirCB->OpenReferenceCount); // // If this is not the root then decrement the open child reference count // if( pObjectInfo->ParentObjectInformation != NULL && pObjectInfo->ParentObjectInformation->Specific.Directory.ChildOpenReferenceCount > 0) { InterlockedDecrement( &pObjectInfo->ParentObjectInformation->Specific.Directory.ChildOpenReferenceCount); AFSDbgLogMsg( AFS_SUBSYSTEM_FCB_REF_COUNTING, AFS_TRACE_LEVEL_VERBOSE, "AFSClose (Share) Decrement child open ref count on Parent object %08lX Cnt %d\n", pObjectInfo->ParentObjectInformation, pObjectInfo->ParentObjectInformation->Specific.Directory.ChildOpenReferenceCount); } AFSReleaseResource( &pFcb->NPFcb->Resource); ASSERT( pFcb->OpenReferenceCount != 0); InterlockedDecrement( &pFcb->OpenReferenceCount); AFSDbgLogMsg( AFS_SUBSYSTEM_FCB_REF_COUNTING, AFS_TRACE_LEVEL_VERBOSE, "AFSClose (Share) Decrement count on Fcb %08lX Cnt %d\n", pFcb, pFcb->OpenReferenceCount); break; } default: AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING, AFS_TRACE_LEVEL_ERROR, "AFSClose Processing unknown node type %d\n", pFcb->Header.NodeTypeCode); break; } try_exit: // // Complete the request // AFSCompleteRequest( Irp, ntStatus); } __except( AFSExceptionFilter( __FUNCTION__, GetExceptionCode(), GetExceptionInformation()) ) { AFSDbgLogMsg( 0, 0, "EXCEPTION - AFSClose\n"); AFSDumpTraceFilesFnc(); } return ntStatus; }
NTSTATUS AFSQuerySecurity( IN PDEVICE_OBJECT LibDeviceObject, IN PIRP Irp) { NTSTATUS ntStatus = STATUS_SUCCESS; PIO_STACK_LOCATION pIrpSp; PMDL pUserBufferMdl = NULL; void *pLockedUserBuffer = NULL; ULONG ulSDLength = 0; __try { pIrpSp = IoGetCurrentIrpStackLocation( Irp); AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING, AFS_TRACE_LEVEL_VERBOSE, "AFSQuerySecurity Entry for FO %08lX\n", pIrpSp->FileObject); if( AFSDefaultSD == NULL) { AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING, AFS_TRACE_LEVEL_ERROR, "AFSQuerySecurity No default SD allocated\n"); try_return( ntStatus = STATUS_INSUFFICIENT_RESOURCES); } ulSDLength = RtlLengthSecurityDescriptor( AFSDefaultSD); if( pIrpSp->Parameters.QuerySecurity.Length < ulSDLength || Irp->UserBuffer == NULL) { AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING, AFS_TRACE_LEVEL_VERBOSE, "AFSQuerySecurity Buffer too small\n"); Irp->IoStatus.Information = (ULONG_PTR)ulSDLength; try_return( ntStatus = STATUS_BUFFER_OVERFLOW); } pLockedUserBuffer = AFSLockUserBuffer( Irp->UserBuffer, pIrpSp->Parameters.QuerySecurity.Length, &pUserBufferMdl); if( pLockedUserBuffer == NULL) { AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING, AFS_TRACE_LEVEL_ERROR, "AFSQuerySecurity Failed to lock user buffer\n"); try_return( ntStatus = STATUS_INSUFFICIENT_RESOURCES); } RtlCopyMemory( pLockedUserBuffer, AFSDefaultSD, ulSDLength); Irp->IoStatus.Information = (ULONG_PTR)ulSDLength; try_exit: if( pUserBufferMdl != NULL) { MmUnlockPages( pUserBufferMdl); IoFreeMdl( pUserBufferMdl); } } __except( AFSExceptionFilter( GetExceptionCode(), GetExceptionInformation()) ) { AFSDbgLogMsg( 0, 0, "EXCEPTION - AFSQuerySecurity\n"); } AFSCompleteRequest( Irp, ntStatus); return ntStatus; }
NTSTATUS AFSCommonCreate( IN PDEVICE_OBJECT DeviceObject, IN PIRP Irp) { NTSTATUS ntStatus = STATUS_SUCCESS; FILE_OBJECT *pFileObject = NULL; IO_STACK_LOCATION *pIrpSp; AFSDeviceExt *pDeviceExt = NULL; AFSDeviceExt *pControlDevExt = (AFSDeviceExt *)AFSDeviceObject->DeviceExtension; GUID *pAuthGroup = NULL; UNICODE_STRING uniGUIDString; __Enter { pIrpSp = IoGetCurrentIrpStackLocation( Irp); pDeviceExt = (AFSDeviceExt *)DeviceObject->DeviceExtension; pFileObject = pIrpSp->FileObject; uniGUIDString.Buffer = NULL; uniGUIDString.Length = 0; uniGUIDString.MaximumLength = 0; // // Validate the process entry // pAuthGroup = AFSValidateProcessEntry(); if( pAuthGroup != NULL) { RtlStringFromGUID( *pAuthGroup, &uniGUIDString); AFSDbgLogMsg( AFS_SUBSYSTEM_AUTHGROUP_PROCESSING, AFS_TRACE_LEVEL_VERBOSE, "%s (%08lX) Located AuthGroup %wZ after validation\n", __FUNCTION__, Irp, &uniGUIDString); } else { AFSDbgLogMsg( AFS_SUBSYSTEM_AUTHGROUP_PROCESSING, AFS_TRACE_LEVEL_VERBOSE, "%s (%08lX) Failed to locate AuthGroup\n", __FUNCTION__, Irp); } // // Root open? // if( pFileObject == NULL || pFileObject->FileName.Buffer == NULL) { AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING, AFS_TRACE_LEVEL_VERBOSE, "AFSCommonCreate (%08lX) Processing volume open request\n", Irp); ntStatus = AFSOpenRedirector( Irp); AFSCompleteRequest( Irp, ntStatus); try_return( ntStatus); } // // Check the state of the library // ntStatus = AFSCheckLibraryState( Irp); if( !NT_SUCCESS( ntStatus) || ntStatus == STATUS_PENDING) { if( ntStatus != STATUS_PENDING) { AFSCompleteRequest( Irp, ntStatus); } try_return( ntStatus); } IoSkipCurrentIrpStackLocation( Irp); ntStatus = IoCallDriver( pControlDevExt->Specific.Control.LibraryDeviceObject, Irp); // // Indicate the library is done with the request // AFSClearLibraryRequest(); try_exit: if ( pFileObject) { AFSDbgLogMsg( AFS_SUBSYSTEM_AUTHGROUP_PROCESSING, AFS_TRACE_LEVEL_VERBOSE, "%s (%08lX) File \"%wZ\" AuthGroup '%wZ' ntStatus %08lX\n", __FUNCTION__, Irp, &pFileObject->FileName, &uniGUIDString, ntStatus); } if( uniGUIDString.Buffer != NULL) { RtlFreeUnicodeString( &uniGUIDString); } } return ntStatus; }
NTSTATUS AFSProcessIrpRequest( IN PIRP Irp) { NTSTATUS ntStatus = STATUS_SUCCESS; AFSDeviceExt *pDevExt = (AFSDeviceExt *)AFSDeviceObject->DeviceExtension; IO_STACK_LOCATION *pIrpSp = IoGetCurrentIrpStackLocation( Irp); AFSCommSrvcCB *pCommSrvc = NULL; AFSPoolEntry *pEntry = NULL, *pPrevEntry = NULL; AFSCommRequest *pRequest = NULL; BOOLEAN bReleaseRequestThread = FALSE; PVOID Objects[2]; __Enter { pCommSrvc = &pDevExt->Specific.Control.CommServiceCB; pRequest = (AFSCommRequest *)Irp->AssociatedIrp.SystemBuffer; AFSDbgLogMsg( AFS_SUBSYSTEM_LOCK_PROCESSING, AFS_TRACE_LEVEL_VERBOSE, "AFSProcessIrpRequest Acquiring IrpPoolLock lock %08lX EXCL %08lX\n", &pCommSrvc->IrpPoolLock, PsGetCurrentThread()); AFSAcquireExcl( &pCommSrvc->IrpPoolLock, TRUE); if( pCommSrvc->IrpPoolControlFlag != POOL_ACTIVE) { AFSReleaseResource( &pCommSrvc->IrpPoolLock); try_return( ntStatus = STATUS_DEVICE_NOT_READY); } AFSReleaseResource( &pCommSrvc->IrpPoolLock); // // Is this a dedicated flush thread? // if( BooleanFlagOn( pRequest->RequestFlags, AFS_REQUEST_RELEASE_THREAD)) { bReleaseRequestThread = TRUE; } // // Populate the objects array for the non release only threads // Release only workers can only process release extent events // whereas normal workers can process any kind of event. // Release only workers are present to ensure there cannot be // a deadlock due to all extents held by the redirector and // there not be a worker available to release them. // Objects[0] = &pCommSrvc->IrpPoolHasReleaseEntries; Objects[1] = &pCommSrvc->IrpPoolHasEntries; // // Wait on the 'have items' event until we can retrieve an item // while( TRUE) { if( bReleaseRequestThread) { ntStatus = KeWaitForSingleObject( &pCommSrvc->IrpPoolHasReleaseEntries, UserRequest, UserMode, TRUE, NULL); if( ntStatus != STATUS_SUCCESS) { ntStatus = STATUS_DEVICE_NOT_READY; break; } } else { ntStatus = KeWaitForMultipleObjects( 2, Objects, WaitAny, UserRequest, UserMode, TRUE, NULL, NULL); if( ntStatus != STATUS_WAIT_0 && ntStatus != STATUS_WAIT_1) { ntStatus = STATUS_DEVICE_NOT_READY; break; } } // // Grab the lock on the request pool // AFSDbgLogMsg( AFS_SUBSYSTEM_LOCK_PROCESSING, AFS_TRACE_LEVEL_VERBOSE, "AFSProcessIrpRequest Acquiring IrpPoolLock (WAIT) lock %08lX EXCL %08lX\n", &pCommSrvc->IrpPoolLock, PsGetCurrentThread()); AFSAcquireExcl( &pCommSrvc->IrpPoolLock, TRUE); if( pCommSrvc->IrpPoolControlFlag != POOL_ACTIVE) { AFSReleaseResource( &pCommSrvc->IrpPoolLock); // // Wake up the next worker since this is a SynchronizationEvent // KeSetEvent( &pCommSrvc->IrpPoolHasReleaseEntries, 0, FALSE); try_return( ntStatus = STATUS_DEVICE_NOT_READY); } // // If this is a dedicated flush thread only look for a flush request in the queue // if( bReleaseRequestThread) { pEntry = pCommSrvc->RequestPoolHead; pPrevEntry = NULL; while( pEntry != NULL) { if( pEntry->RequestType == AFS_REQUEST_TYPE_RELEASE_FILE_EXTENTS) { if( pPrevEntry == NULL) { pCommSrvc->RequestPoolHead = pEntry->fLink; if( pCommSrvc->RequestPoolHead == NULL) { pCommSrvc->RequestPoolTail = NULL; } } else { pPrevEntry->fLink = pEntry->fLink; if( pPrevEntry->fLink == NULL) { pCommSrvc->RequestPoolTail = pPrevEntry; } } break; } pPrevEntry = pEntry; pEntry = pEntry->fLink; } if( pEntry != NULL) { // // There might be another release entry pending // KeSetEvent( &pCommSrvc->IrpPoolHasReleaseEntries, 0, FALSE); } // // And release the request pool lock // AFSReleaseResource( &pCommSrvc->IrpPoolLock); } else { pEntry = pCommSrvc->RequestPoolHead; if( pEntry != NULL) { pCommSrvc->RequestPoolHead = pEntry->fLink; pEntry->bLink = NULL; if( pCommSrvc->RequestPoolHead == NULL) { pCommSrvc->RequestPoolTail = NULL; } else { KeSetEvent( &pCommSrvc->IrpPoolHasEntries, 0, FALSE); } } // // And release the request pool lock // AFSReleaseResource( &pCommSrvc->IrpPoolLock); } // // Insert the entry into the result pool, if we have one // if( pEntry != NULL) { // // Move the request data into the passed in buffer // ASSERT( sizeof( AFSCommRequest) + pEntry->FileName.Length + pEntry->DataLength <= pIrpSp->Parameters.DeviceIoControl.OutputBufferLength); RtlCopyMemory( &pRequest->AuthGroup, &pEntry->AuthGroup, sizeof( GUID)); pRequest->FileId = pEntry->FileId; pRequest->RequestType = pEntry->RequestType; pRequest->RequestIndex = pEntry->RequestIndex; pRequest->RequestFlags = pEntry->RequestFlags; pRequest->NameLength = pEntry->FileName.Length; pRequest->QueueCount = InterlockedDecrement( &pCommSrvc->QueueCount); if( pRequest->NameLength > 0) { RtlCopyMemory( pRequest->Name, pEntry->FileName.Buffer, pRequest->NameLength); } pRequest->DataOffset = 0; pRequest->DataLength = pEntry->DataLength; if( pRequest->DataLength > 0) { pRequest->DataOffset = pEntry->FileName.Length; RtlCopyMemory( (void *)((char *)pRequest->Name + pRequest->DataOffset), pEntry->Data, pRequest->DataLength); } pRequest->ResultBufferLength = 0; if( pEntry->ResultBufferLength != NULL) { pRequest->ResultBufferLength = *(pEntry->ResultBufferLength); } Irp->IoStatus.Information = sizeof( AFSCommRequest) + pEntry->FileName.Length + pEntry->DataLength; // // If this is a synchronous request then move the request into the // result pool // if( BooleanFlagOn( pEntry->RequestFlags, AFS_REQUEST_FLAG_SYNCHRONOUS)) { pEntry->fLink = NULL; pEntry->bLink = NULL; AFSDbgLogMsg( AFS_SUBSYSTEM_LOCK_PROCESSING, AFS_TRACE_LEVEL_VERBOSE, "AFSProcessIrpRequest Acquiring ResultPoolLock lock %08lX EXCL %08lX\n", &pCommSrvc->ResultPoolLock, PsGetCurrentThread()); AFSAcquireExcl( &pCommSrvc->ResultPoolLock, TRUE); if( pCommSrvc->ResultPoolHead == NULL) { pCommSrvc->ResultPoolHead = pEntry; } else { pCommSrvc->ResultPoolTail->fLink = pEntry; pEntry->bLink = pCommSrvc->ResultPoolTail; } pCommSrvc->ResultPoolTail = pEntry; AFSReleaseResource( &pCommSrvc->ResultPoolLock); } else { // // Free up the pool entry // ExFreePool( pEntry); } break; } } try_exit: NOTHING; } return ntStatus; }
NTSTATUS AFSProcessShareFsCtrl( IN IRP *Irp, IN AFSFcb *Fcb, IN AFSCcb *Ccb) { NTSTATUS ntStatus = STATUS_SUCCESS; PIO_STACK_LOCATION pIrpSp = IoGetCurrentIrpStackLocation( Irp); ULONG ulOutputBufferLen = 0, ulInputBufferLen; ULONG ulFsControlCode; __Enter { ulFsControlCode = pIrpSp->Parameters.FileSystemControl.FsControlCode; ulOutputBufferLen = pIrpSp->Parameters.FileSystemControl.OutputBufferLength; ulInputBufferLen = pIrpSp->Parameters.FileSystemControl.InputBufferLength; switch( ulFsControlCode) { case FSCTL_PIPE_TRANSCEIVE: { AFSDbgLogMsg( AFS_SUBSYSTEM_PIPE_PROCESSING, AFS_TRACE_LEVEL_VERBOSE, "AFSProcessShareFsCtrl On pipe %wZ Class FSCTL_PIPE_TRANSCEIVE\n", &Ccb->DirectoryCB->NameInformation.FileName); ntStatus = AFSNotifyPipeTransceive( Ccb, ulInputBufferLen, ulOutputBufferLen, pIrpSp->Parameters.FileSystemControl.Type3InputBuffer, Irp->UserBuffer, (ULONG *)&Irp->IoStatus.Information); if( !NT_SUCCESS( ntStatus)) { AFSDbgLogMsg( AFS_SUBSYSTEM_PIPE_PROCESSING, AFS_TRACE_LEVEL_VERBOSE, "AFSProcessShareFsCtrl Failure on pipe %wZ Class FSCTL_PIPE_TRANSCEIVE Status %08lX\n", &Ccb->DirectoryCB->NameInformation.FileName, ntStatus); } break; } 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); } break; } } } 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->DirectoryCB == NULL) { AFSDbgLogMsg( 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: { 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: { REPARSE_GUID_DATA_BUFFER *pReparseBuffer = (REPARSE_GUID_DATA_BUFFER *)Irp->AssociatedIrp.SystemBuffer; ULONG ulRemainingLen = ulOutputBufferLen; AFSReparseTagInfo *pReparseInfo = NULL; AFSDbgLogMsg( 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, 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)) { ntStatus = STATUS_NOT_A_REPARSE_POINT; 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 // 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 // pCcb->DirectoryCB->ObjectInformation->DataVersion.QuadPart = (ULONGLONG)-1; SetFlag( pCcb->DirectoryCB->ObjectInformation->Flags, AFS_OBJECT_FLAGS_VERIFY); AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING, AFS_TRACE_LEVEL_VERBOSE, "AFSProcessUserFsRequest Verifying symlink %wZ FID %08lX-%08lX-%08lX-%08lX\n", &pCcb->DirectoryCB->NameInformation.FileName, pCcb->DirectoryCB->ObjectInformation->FileId.Cell, pCcb->DirectoryCB->ObjectInformation->FileId.Volume, pCcb->DirectoryCB->ObjectInformation->FileId.Vnode, pCcb->DirectoryCB->ObjectInformation->FileId.Unique); ntStatus = AFSVerifyEntry( &pCcb->AuthGroup, pCcb->DirectoryCB); if( !NT_SUCCESS( ntStatus)) { AFSDbgLogMsg( 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, pCcb->DirectoryCB->ObjectInformation->FileId.Cell, pCcb->DirectoryCB->ObjectInformation->FileId.Volume, pCcb->DirectoryCB->ObjectInformation->FileId.Vnode, pCcb->DirectoryCB->ObjectInformation->FileId.Unique, ntStatus); AFSReleaseResource( &pCcb->DirectoryCB->NonPaged->Lock); break; } } pReparseInfo = (AFSReparseTagInfo *)&pReparseBuffer->GenericReparseBuffer.DataBuffer[ 0]; switch( pCcb->DirectoryCB->ObjectInformation->FileType) { case AFS_FILE_TYPE_SYMLINK: { if( pCcb->DirectoryCB->NameInformation.TargetName.Length == 0) { ntStatus = STATUS_REPARSE_POINT_NOT_RESOLVED; break; } if( ulRemainingLen < (ULONG) FIELD_OFFSET( AFSReparseTagInfo, AFSSymLink.Buffer) + pCcb->DirectoryCB->NameInformation.TargetName.Length) { ntStatus = STATUS_BUFFER_TOO_SMALL; Irp->IoStatus.Information = FIELD_OFFSET( REPARSE_GUID_DATA_BUFFER, GenericReparseBuffer.DataBuffer) + FIELD_OFFSET( AFSReparseTagInfo, AFSSymLink.Buffer) + pCcb->DirectoryCB->NameInformation.TargetName.Length; break; } pReparseInfo->SubTag = OPENAFS_SUBTAG_SYMLINK; pReparseInfo->AFSSymLink.RelativeLink = AFSIsRelativeName( &pCcb->DirectoryCB->NameInformation.TargetName); pReparseInfo->AFSSymLink.SymLinkTargetLength = pCcb->DirectoryCB->NameInformation.TargetName.Length; RtlCopyMemory( pReparseInfo->AFSSymLink.Buffer, pCcb->DirectoryCB->NameInformation.TargetName.Buffer, pCcb->DirectoryCB->NameInformation.TargetName.Length); pReparseBuffer->ReparseDataLength = (FIELD_OFFSET( AFSReparseTagInfo, AFSSymLink.Buffer) + pCcb->DirectoryCB->NameInformation.TargetName.Length); 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; } if( ulRemainingLen < (ULONG) FIELD_OFFSET( AFSReparseTagInfo, UNCReferral.Buffer) + pCcb->DirectoryCB->NameInformation.TargetName.Length) { ntStatus = STATUS_BUFFER_TOO_SMALL; Irp->IoStatus.Information = FIELD_OFFSET( REPARSE_GUID_DATA_BUFFER, GenericReparseBuffer.DataBuffer) + FIELD_OFFSET( AFSReparseTagInfo, UNCReferral.Buffer) + pCcb->DirectoryCB->NameInformation.TargetName.Length; break; } pReparseInfo->SubTag = OPENAFS_SUBTAG_UNC; pReparseInfo->UNCReferral.UNCTargetLength = pCcb->DirectoryCB->NameInformation.TargetName.Length; RtlCopyMemory( pReparseInfo->UNCReferral.Buffer, pCcb->DirectoryCB->NameInformation.TargetName.Buffer, pCcb->DirectoryCB->NameInformation.TargetName.Length); pReparseBuffer->ReparseDataLength = (FIELD_OFFSET( AFSReparseTagInfo, UNCReferral.Buffer) + pCcb->DirectoryCB->NameInformation.TargetName.Length); break; } default: ntStatus = STATUS_NOT_A_REPARSE_POINT; break; } if ( ntStatus == STATUS_SUCCESS) { ulRemainingLen -= pReparseBuffer->ReparseDataLength; 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; } AFSReleaseResource( &pCcb->DirectoryCB->NonPaged->Lock); break; } case FSCTL_SET_REPARSE_POINT: { REPARSE_GUID_DATA_BUFFER *pReparseBuffer = (REPARSE_GUID_DATA_BUFFER *)Irp->AssociatedIrp.SystemBuffer; AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING, AFS_TRACE_LEVEL_VERBOSE_2, "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)) { ntStatus = STATUS_NOT_A_REPARSE_POINT; break; } if( ulInputBufferLen < FIELD_OFFSET( REPARSE_GUID_DATA_BUFFER, GenericReparseBuffer.DataBuffer)) { ntStatus = STATUS_IO_REPARSE_DATA_INVALID; 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; } // // For now deny access on this call // ntStatus = STATUS_INVALID_PARAMETER; break; } case FSCTL_DELETE_REPARSE_POINT: { REPARSE_GUID_DATA_BUFFER *pReparseBuffer = (REPARSE_GUID_DATA_BUFFER *)Irp->AssociatedIrp.SystemBuffer; AFSDbgLogMsg( 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, 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)) { 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; } // // For now deny access on this call // ntStatus = STATUS_ACCESS_DENIED; break; } default : AFSDbgLogMsg( 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; }
void AFSCleanupIrpPool() { NTSTATUS ntStatus = STATUS_SUCCESS; AFSPoolEntry *pEntry = NULL, *pNextEntry = NULL; AFSDeviceExt *pDevExt = (AFSDeviceExt *)AFSDeviceObject->DeviceExtension; AFSCommSrvcCB *pCommSrvc = (AFSCommSrvcCB *)&pDevExt->Specific.Control.CommServiceCB; __Enter { // // When we change the state, grab both pool locks exclusive. The order is always the // Irp pool then the result pool lock // AFSDbgLogMsg( AFS_SUBSYSTEM_LOCK_PROCESSING, AFS_TRACE_LEVEL_VERBOSE, "AFSCleanupIrpPool Acquiring IrpPoolLock lock %08lX EXCL %08lX\n", &pCommSrvc->IrpPoolLock, PsGetCurrentThread()); AFSAcquireExcl( &pCommSrvc->IrpPoolLock, TRUE); AFSDbgLogMsg( AFS_SUBSYSTEM_LOCK_PROCESSING, AFS_TRACE_LEVEL_VERBOSE, "AFSCleanupIrpPool Acquiring ResultPoolLock lock %08lX EXCL %08lX\n", &pCommSrvc->ResultPoolLock, PsGetCurrentThread()); AFSAcquireExcl( &pCommSrvc->ResultPoolLock, TRUE); // // Indicate we are pending stop // pCommSrvc->IrpPoolControlFlag = POOL_INACTIVE; // // Set the event to release any waiting workers // (everyone waits on IrpPoolHasReleaseEntries) // KeSetEvent( &pCommSrvc->IrpPoolHasReleaseEntries, 0, FALSE); // // Go through the pool entries and free up the structures. // pEntry = pCommSrvc->RequestPoolHead; while( pEntry != NULL) { pNextEntry = pEntry->fLink; if( BooleanFlagOn( pEntry->RequestFlags, AFS_REQUEST_FLAG_SYNCHRONOUS)) { // // Here we need to complete the irp, cancelled, and delete the data block // pEntry->ResultStatus = STATUS_CANCELLED; KeSetEvent( &pEntry->Event, 0, FALSE); } else { ExFreePool( pEntry); } pEntry = pNextEntry; } // // Cleanup the control structure for the request pool // pCommSrvc->RequestPoolHead = NULL; pCommSrvc->RequestPoolTail = NULL; pCommSrvc->IrpPoolRequestIndex = 1; KeClearEvent( &pCommSrvc->IrpPoolHasEntries); KeClearEvent( &pCommSrvc->IrpPoolHasReleaseEntries); // // Release the irp pool lock. // AFSReleaseResource( &pCommSrvc->IrpPoolLock); // // Go through the result pool entries and free up the structures. // pEntry = pCommSrvc->ResultPoolHead; while( pEntry != NULL) { pNextEntry = pEntry->fLink; pEntry->ResultStatus = STATUS_CANCELLED; // // Here we will set the event of the requestor and let the blocked thread // free the data block // KeSetEvent( &pEntry->Event, 0, FALSE); // // Go onto the next entry // pEntry = pNextEntry; } // // Cleanup the control structure for the result pool // pCommSrvc->ResultPoolHead = NULL; pCommSrvc->ResultPoolTail = NULL; // // Release the result pool lock. // AFSReleaseResource( &pCommSrvc->ResultPoolLock); } return; }
NTSTATUS AFSInitIrpPool() { NTSTATUS ntStatus = STATUS_SUCCESS; AFSCommSrvcCB *pCommSrvc = NULL; BOOLEAN bReleasePools = FALSE; AFSDeviceExt *pDevExt = (AFSDeviceExt *)AFSDeviceObject->DeviceExtension; __Enter { pCommSrvc = &pDevExt->Specific.Control.CommServiceCB; // // Whenever we change state we must grab both pool locks. On the checking of the state // within the processing routines for these respective pools, we only grab one lock to // minimize serialization. The ordering is always the Irp pool then the result pool // locks. We also do this in the tear down of the pool // AFSDbgLogMsg( AFS_SUBSYSTEM_LOCK_PROCESSING, AFS_TRACE_LEVEL_VERBOSE, "AFSInitIrpPool Acquiring IrpPoolLock lock %08lX EXCL %08lX\n", &pCommSrvc->IrpPoolLock, PsGetCurrentThread()); AFSAcquireExcl( &pCommSrvc->IrpPoolLock, TRUE); AFSDbgLogMsg( AFS_SUBSYSTEM_LOCK_PROCESSING, AFS_TRACE_LEVEL_VERBOSE, "AFSInitIrpPool Acquiring ResultPoolLock lock %08lX EXCL %08lX\n", &pCommSrvc->ResultPoolLock, PsGetCurrentThread()); AFSAcquireExcl( &pCommSrvc->ResultPoolLock, TRUE); bReleasePools = TRUE; // // The pool can be either ACTIVE or INACTIVE. If the pool state is INACTIVE and we // are receiving the INIT request, then activate it. If the pool is ACTIVE, then we // shouldn't be getting this request ... // if( pCommSrvc->IrpPoolControlFlag == POOL_ACTIVE) { // // We have already been activated so just fail this request // try_return( ntStatus = STATUS_INVALID_PARAMETER); } else if( pCommSrvc->IrpPoolControlFlag == POOL_INACTIVE) { // // The pool is currently INACTIVE so start it up and ready it to // receive irp requests // pCommSrvc->IrpPoolControlFlag = POOL_ACTIVE; pDevExt->Specific.Control.ServiceProcess = (PKPROCESS)PsGetCurrentProcess(); try_return( ntStatus = STATUS_SUCCESS); } else { // // The pool is in some mixed state, fail the request. // try_return( ntStatus = STATUS_DEVICE_NOT_READY); } try_exit: if( bReleasePools) { AFSReleaseResource( &pCommSrvc->IrpPoolLock); AFSReleaseResource( &pCommSrvc->ResultPoolLock); } } return ntStatus; }
NTSTATUS AFSQueryEA( IN PDEVICE_OBJECT DeviceObject, IN PIRP Irp) { NTSTATUS ntStatus = STATUS_EAS_NOT_SUPPORTED; AFSDeviceExt *pControlDeviceExt = (AFSDeviceExt *)AFSDeviceObject->DeviceExtension; __try { if( DeviceObject == AFSDeviceObject) { AFSCompleteRequest( Irp, ntStatus); try_return( ntStatus); } // // Check the state of the library // ntStatus = AFSCheckLibraryState( Irp); if( !NT_SUCCESS( ntStatus) || ntStatus == STATUS_PENDING) { if( ntStatus != STATUS_PENDING) { AFSCompleteRequest( Irp, ntStatus); } try_return( ntStatus); } IoSkipCurrentIrpStackLocation( Irp); ntStatus = IoCallDriver( pControlDeviceExt->Specific.Control.LibraryDeviceObject, Irp); // // Indicate the library is done with the request // AFSClearLibraryRequest(); try_exit: NOTHING; } __except( AFSExceptionFilter( __FUNCTION__, GetExceptionCode(), GetExceptionInformation()) ) { AFSDbgLogMsg( 0, 0, "EXCEPTION - AFSQueryEA\n"); AFSDumpTraceFilesFnc(); } return ntStatus; }
NTSTATUS AFSSetSecurity( IN PDEVICE_OBJECT DeviceObject, IN PIRP Irp) { NTSTATUS ntStatus = STATUS_NOT_SUPPORTED; IO_STACK_LOCATION *pIrpSp; AFSDeviceExt *pControlDeviceExt = (AFSDeviceExt *)AFSDeviceObject->DeviceExtension; pIrpSp = IoGetCurrentIrpStackLocation( Irp); __try { AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING, AFS_TRACE_LEVEL_VERBOSE, "AFSSetSecurity Entry for FO %08lX\n", pIrpSp->FileObject); if( DeviceObject == AFSDeviceObject) { ntStatus = STATUS_INVALID_DEVICE_REQUEST; AFSCompleteRequest( Irp, ntStatus); try_return( ntStatus); } if( pIrpSp->FileObject->FsContext == NULL) { // // Root open // ntStatus = STATUS_INVALID_DEVICE_REQUEST; AFSCompleteRequest( Irp, ntStatus); try_return( ntStatus); } // // Check the state of the library // ntStatus = AFSCheckLibraryState( Irp); if( !NT_SUCCESS( ntStatus) || ntStatus == STATUS_PENDING) { if( ntStatus != STATUS_PENDING) { AFSCompleteRequest( Irp, ntStatus); } try_return( ntStatus); } IoSkipCurrentIrpStackLocation( Irp); ntStatus = IoCallDriver( pControlDeviceExt->Specific.Control.LibraryDeviceObject, Irp); // // Indicate the library is done with the request // AFSClearLibraryRequest(); try_exit: NOTHING; } __except( AFSExceptionFilter( GetExceptionCode(), GetExceptionInformation()) ) { AFSDbgLogMsg( 0, 0, "EXCEPTION - AFSSetSecurity\n"); } return ntStatus; }
void AFSRemoveFcb( IN AFSFcb *Fcb) { // // Uninitialize the file lock if it is a file // AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING, AFS_TRACE_LEVEL_VERBOSE, "AFSRemoveFcb Removing Fcb %08lX\n", Fcb); if( Fcb->Header.NodeTypeCode == AFS_FILE_FCB) { FsRtlUninitializeFileLock( &Fcb->Specific.File.FileLock); // // The resource we allocated // ExDeleteResourceLite( &Fcb->NPFcb->Specific.File.ExtentsResource ); ExDeleteResourceLite( &Fcb->NPFcb->Specific.File.DirtyExtentsListLock); } else if( Fcb->Header.NodeTypeCode == AFS_DIRECTORY_FCB) { } // // Tear down the FM specific contexts // FsRtlTeardownPerStreamContexts( &Fcb->Header); // // Delete the resources // ExDeleteResourceLite( &Fcb->NPFcb->Resource); ExDeleteResourceLite( &Fcb->NPFcb->PagingResource); ExDeleteResourceLite( &Fcb->NPFcb->CcbListLock); // // The non paged region // AFSExFreePool( Fcb->NPFcb); // // And the Fcb itself, which includes the name // AFSExFreePool( Fcb); return; }
NTSTATUS AFSCleanup( IN PDEVICE_OBJECT DeviceObject, IN PIRP Irp) { NTSTATUS ntStatus = STATUS_SUCCESS; AFSDeviceExt *pDeviceExt = (AFSDeviceExt *)DeviceObject->DeviceExtension; IO_STACK_LOCATION *pIrpSp = IoGetCurrentIrpStackLocation( Irp); __try { // // Set some initial variables to make processing easier // if( DeviceObject == AFSDeviceObject) { if( FlagOn( (ULONG_PTR)pIrpSp->FileObject->FsContext, AFS_CONTROL_INSTANCE)) { // // This is the process which was registered for the callback pool so cleanup the pool // AFSCleanupIrpPool(); } if( FlagOn( (ULONG_PTR)pIrpSp->FileObject->FsContext, AFS_REDIRECTOR_INSTANCE)) { // // Close the redirector // AFSCloseRedirector(); } AFSCompleteRequest( Irp, ntStatus); try_return( ntStatus); } ntStatus = AFSCommonCleanup( DeviceObject, Irp); try_exit: NOTHING; } __except( AFSExceptionFilter( GetExceptionCode(), GetExceptionInformation()) ) { AFSDbgLogMsg( 0, 0, "EXCEPTION - AFSCleanup\n"); } return ntStatus; }
NTSTATUS AFSInitVolume( IN GUID *AuthGroup, IN AFSFileID *RootFid, OUT AFSVolumeCB **VolumeCB) { NTSTATUS ntStatus = STATUS_SUCCESS; IO_STATUS_BLOCK stIoStatus = {0,0}; AFSDeviceExt *pDeviceExt = (AFSDeviceExt *)AFSRDRDeviceObject->DeviceExtension; AFSNonPagedVolumeCB *pNonPagedVcb = NULL; AFSVolumeCB *pVolumeCB = NULL; AFSNonPagedObjectInfoCB *pNonPagedObject = NULL; ULONGLONG ullIndex = 0; BOOLEAN bReleaseLocks = FALSE; AFSVolumeInfoCB stVolumeInformation; AFSNonPagedDirectoryCB *pNonPagedDirEntry = NULL; __Enter { // // Before grabbing any locks ask the service for the volume information // This may be a waste but we need to get this information prior to // taking any volume tree locks. Don't do this for any 'reserved' cell entries // if( RootFid->Cell != 0) { RtlZeroMemory( &stVolumeInformation, sizeof( AFSVolumeInfoCB)); ntStatus = AFSRetrieveVolumeInformation( AuthGroup, RootFid, &stVolumeInformation); if( !NT_SUCCESS( ntStatus)) { AFSDbgLogMsg( AFS_SUBSYSTEM_LOAD_LIBRARY | AFS_SUBSYSTEM_INIT_PROCESSING, AFS_TRACE_LEVEL_ERROR, "AFSInitVolume AFSRetrieveVolumeInformation(RootFid) failure %08lX\n", ntStatus); try_return( ntStatus); } // // Grab our tree locks and see if we raced with someone else // AFSAcquireExcl( pDeviceExt->Specific.RDR.VolumeTree.TreeLock, TRUE); AFSAcquireExcl( &pDeviceExt->Specific.RDR.VolumeListLock, TRUE); bReleaseLocks = TRUE; ullIndex = AFSCreateHighIndex( RootFid); ntStatus = AFSLocateHashEntry( pDeviceExt->Specific.RDR.VolumeTree.TreeHead, ullIndex, (AFSBTreeEntry **)&pVolumeCB); if( NT_SUCCESS( ntStatus) && pVolumeCB != NULL) { // // So we don't lock with an invalidation call ... // InterlockedIncrement( &pVolumeCB->VolumeReferenceCount); AFSReleaseResource( pDeviceExt->Specific.RDR.VolumeTree.TreeLock); AFSReleaseResource( &pDeviceExt->Specific.RDR.VolumeListLock); bReleaseLocks = FALSE; AFSAcquireExcl( pVolumeCB->VolumeLock, TRUE); InterlockedDecrement( &pVolumeCB->VolumeReferenceCount); *VolumeCB = pVolumeCB; try_return( ntStatus); } // // Revert our status from the above call back to success. // ntStatus = STATUS_SUCCESS; } // // For the global root we allocate out volume node and insert it // into the volume tree ... // pVolumeCB = (AFSVolumeCB *)AFSExAllocatePoolWithTag( NonPagedPool, sizeof( AFSVolumeCB), AFS_VCB_ALLOCATION_TAG); if( pVolumeCB == NULL) { AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING, AFS_TRACE_LEVEL_ERROR, "AFSInitVolume Failed to allocate the root volume cb\n"); try_return( ntStatus = STATUS_INSUFFICIENT_RESOURCES); } RtlZeroMemory( pVolumeCB, sizeof( AFSVolumeCB)); // // The non paged portion // pNonPagedVcb = (AFSNonPagedVolumeCB *)AFSExAllocatePoolWithTag( NonPagedPool, sizeof( AFSNonPagedVolumeCB), AFS_VCB_ALLOCATION_TAG); if( pNonPagedVcb == NULL) { AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING, AFS_TRACE_LEVEL_ERROR, "AFSInitVolume Failed to allocate the root non paged volume cb\n"); try_return( ntStatus = STATUS_INSUFFICIENT_RESOURCES); } RtlZeroMemory( pNonPagedVcb, sizeof( AFSNonPagedVolumeCB)); ExInitializeResourceLite( &pNonPagedVcb->VolumeLock); ExInitializeResourceLite( &pNonPagedVcb->ObjectInfoTreeLock); pNonPagedObject = (AFSNonPagedObjectInfoCB *)AFSExAllocatePoolWithTag( NonPagedPool, sizeof( AFSNonPagedObjectInfoCB), AFS_VCB_ALLOCATION_TAG); if( pNonPagedObject == NULL) { AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING, AFS_TRACE_LEVEL_ERROR, "AFSInitVolume Failed to allocate the root non paged object cb\n"); try_return( ntStatus = STATUS_INSUFFICIENT_RESOURCES); } RtlZeroMemory( pNonPagedObject, sizeof( AFSNonPagedObjectInfoCB)); ExInitializeResourceLite( &pNonPagedObject->DirectoryNodeHdrLock); pVolumeCB->NonPagedVcb = pNonPagedVcb; pVolumeCB->ObjectInformation.NonPagedInfo = pNonPagedObject; pVolumeCB->VolumeLock = &pNonPagedVcb->VolumeLock; pVolumeCB->ObjectInformation.Specific.Directory.DirectoryNodeHdr.TreeLock = &pNonPagedObject->DirectoryNodeHdrLock; pVolumeCB->ObjectInfoTree.TreeLock = &pNonPagedVcb->ObjectInfoTreeLock; // // Bias our reference by 1 // AFSDbgLogMsg( AFS_SUBSYSTEM_VOLUME_REF_COUNTING, AFS_TRACE_LEVEL_VERBOSE, "AFSInitVolume Initializing count (1) on volume %08lX\n", pVolumeCB); pVolumeCB->VolumeReferenceCount = 1; AFSAcquireExcl( pVolumeCB->VolumeLock, TRUE); pVolumeCB->DirectoryCB = (AFSDirectoryCB *)AFSExAllocatePoolWithTag( PagedPool, sizeof( AFSDirectoryCB) + sizeof( WCHAR), AFS_DIR_ENTRY_TAG); if( pVolumeCB->DirectoryCB == NULL) { try_return( ntStatus = STATUS_INSUFFICIENT_RESOURCES); } pNonPagedDirEntry = (AFSNonPagedDirectoryCB *)AFSExAllocatePoolWithTag( NonPagedPool, sizeof( AFSNonPagedDirectoryCB), AFS_DIR_ENTRY_NP_TAG); if( pNonPagedDirEntry == NULL) { try_return( ntStatus = STATUS_INSUFFICIENT_RESOURCES); } RtlZeroMemory( pVolumeCB->DirectoryCB, sizeof( AFSDirectoryCB) + sizeof( WCHAR)); RtlZeroMemory( pNonPagedDirEntry, sizeof( AFSNonPagedDirectoryCB)); ExInitializeResourceLite( &pNonPagedDirEntry->Lock); pVolumeCB->DirectoryCB->NonPaged = pNonPagedDirEntry; // // Initialize the non-paged portion of the directory entry // KeQuerySystemTime( &pVolumeCB->ObjectInformation.CreationTime); KeQuerySystemTime( &pVolumeCB->ObjectInformation.LastWriteTime); KeQuerySystemTime( &pVolumeCB->ObjectInformation.LastAccessTime); pVolumeCB->ObjectInformation.FileType = AFS_FILE_TYPE_DIRECTORY; SetFlag( pVolumeCB->ObjectInformation.Flags, AFS_OBJECT_ROOT_VOLUME); pVolumeCB->ObjectInformation.FileId.Cell = RootFid->Cell; pVolumeCB->ObjectInformation.FileId.Volume = RootFid->Volume; pVolumeCB->ObjectInformation.FileId.Vnode = RootFid->Vnode; pVolumeCB->ObjectInformation.FileId.Unique = RootFid->Unique; pVolumeCB->ObjectInformation.FileId.Hash = RootFid->Hash; pVolumeCB->ObjectInformation.FileAttributes = FILE_ATTRIBUTE_DIRECTORY; pVolumeCB->DirectoryCB->NameInformation.FileName.Length = sizeof( WCHAR); pVolumeCB->DirectoryCB->NameInformation.FileName.MaximumLength = pVolumeCB->DirectoryCB->NameInformation.FileName.Length; pVolumeCB->DirectoryCB->NameInformation.FileName.Buffer = (WCHAR *)((char *)pVolumeCB->DirectoryCB + sizeof( AFSDirectoryCB)); RtlCopyMemory( pVolumeCB->DirectoryCB->NameInformation.FileName.Buffer, L"\\", sizeof( WCHAR)); // // Copy in the volume information retrieved above // RtlCopyMemory( &pVolumeCB->VolumeInformation, &stVolumeInformation, sizeof( AFSVolumeInfoCB)); // // Setup pointers // pVolumeCB->DirectoryCB->ObjectInformation = &pVolumeCB->ObjectInformation; pVolumeCB->DirectoryCB->ObjectInformation->VolumeCB = pVolumeCB; // // Insert the volume into our volume tree. Don't insert any reserved entries // if( RootFid->Cell != 0) { pVolumeCB->TreeEntry.HashIndex = ullIndex; if( pDeviceExt->Specific.RDR.VolumeTree.TreeHead == NULL) { pDeviceExt->Specific.RDR.VolumeTree.TreeHead = &pVolumeCB->TreeEntry; SetFlag( pVolumeCB->Flags, AFS_VOLUME_INSERTED_HASH_TREE); } else { if ( NT_SUCCESS( AFSInsertHashEntry( pDeviceExt->Specific.RDR.VolumeTree.TreeHead, &pVolumeCB->TreeEntry))) { SetFlag( pVolumeCB->Flags, AFS_VOLUME_INSERTED_HASH_TREE); } } if( pDeviceExt->Specific.RDR.VolumeListHead == NULL) { pDeviceExt->Specific.RDR.VolumeListHead = pVolumeCB; } else { pDeviceExt->Specific.RDR.VolumeListTail->ListEntry.fLink = (void *)pVolumeCB; pVolumeCB->ListEntry.bLink = pDeviceExt->Specific.RDR.VolumeListTail; } pDeviceExt->Specific.RDR.VolumeListTail = pVolumeCB; } *VolumeCB = pVolumeCB; try_exit: if( !NT_SUCCESS( ntStatus)) { if( pNonPagedVcb != NULL) { AFSReleaseResource( pVolumeCB->VolumeLock); ExDeleteResourceLite( &pNonPagedVcb->VolumeLock); ExDeleteResourceLite( &pNonPagedVcb->ObjectInfoTreeLock); AFSExFreePool( pNonPagedVcb); } if( pNonPagedObject != NULL) { ExDeleteResourceLite( &pNonPagedObject->DirectoryNodeHdrLock); AFSExFreePool( pNonPagedObject); } if( pVolumeCB != NULL) { if( pVolumeCB->DirectoryCB != NULL) { AFSExFreePool( pVolumeCB->DirectoryCB); } AFSExFreePool( pVolumeCB); } if( pNonPagedDirEntry != NULL) { ExDeleteResourceLite( &pNonPagedDirEntry->Lock); AFSExFreePool( pNonPagedDirEntry); } } if( bReleaseLocks) { AFSReleaseResource( pDeviceExt->Specific.RDR.VolumeTree.TreeLock); AFSReleaseResource( &pDeviceExt->Specific.RDR.VolumeListLock); } } return ntStatus; }
NTSTATUS AFSDevControl( IN PDEVICE_OBJECT LibDeviceObject, IN PIRP Irp) { NTSTATUS ntStatus = STATUS_SUCCESS; IO_STACK_LOCATION *pIrpSp; ULONG ulIoControlCode; __try { pIrpSp = IoGetCurrentIrpStackLocation( Irp); ulIoControlCode = pIrpSp->Parameters.DeviceIoControl.IoControlCode; switch( ulIoControlCode) { case IOCTL_AFS_INITIALIZE_LIBRARY_DEVICE: { AFSLibraryInitCB *pLibInitCB = (AFSLibraryInitCB *)Irp->AssociatedIrp.SystemBuffer; if( pIrpSp->Parameters.DeviceIoControl.InputBufferLength < sizeof( AFSLibraryInitCB)) { ntStatus = STATUS_INVALID_PARAMETER; break; } ntStatus = AFSInitializeLibrary( pLibInitCB); if( !NT_SUCCESS( ntStatus)) { AFSDbgLogMsg( AFS_SUBSYSTEM_LOAD_LIBRARY | AFS_SUBSYSTEM_INIT_PROCESSING, AFS_TRACE_LEVEL_ERROR, "AFSDevControl AFSInitializeLibrary failure %08lX\n", ntStatus); break; } // // Initialize our global entries // ntStatus = AFSInitializeGlobalDirectoryEntries(); if( !NT_SUCCESS( ntStatus)) { AFSDbgLogMsg( AFS_SUBSYSTEM_LOAD_LIBRARY | AFS_SUBSYSTEM_INIT_PROCESSING, AFS_TRACE_LEVEL_ERROR, "AFSDevControl AFSInitializeGlobalDirectoryEntries failure %08lX\n", ntStatus); break; } ntStatus = AFSInitializeSpecialShareNameList(); if( !NT_SUCCESS( ntStatus)) { AFSDbgLogMsg( AFS_SUBSYSTEM_LOAD_LIBRARY | AFS_SUBSYSTEM_INIT_PROCESSING, AFS_TRACE_LEVEL_ERROR, "AFSDevControl AFSInitializeSpecialShareNameList failure %08lX\n", ntStatus); break; } break; } case IOCTL_AFS_ADD_CONNECTION: { AFSNetworkProviderConnectionCB *pConnectCB = (AFSNetworkProviderConnectionCB *)Irp->AssociatedIrp.SystemBuffer; if( pIrpSp->Parameters.DeviceIoControl.InputBufferLength < sizeof( AFSNetworkProviderConnectionCB) || pIrpSp->Parameters.DeviceIoControl.InputBufferLength < (ULONG)FIELD_OFFSET( AFSNetworkProviderConnectionCB, RemoteName) + pConnectCB->RemoteNameLength || pIrpSp->Parameters.DeviceIoControl.OutputBufferLength < sizeof( ULONG)) { ntStatus = STATUS_INVALID_PARAMETER; break; } ntStatus = AFSAddConnection( pConnectCB, (PULONG)Irp->AssociatedIrp.SystemBuffer, &Irp->IoStatus.Information); break; } case IOCTL_AFS_CANCEL_CONNECTION: { AFSNetworkProviderConnectionCB *pConnectCB = (AFSNetworkProviderConnectionCB *)Irp->AssociatedIrp.SystemBuffer; if( pIrpSp->Parameters.DeviceIoControl.InputBufferLength < sizeof( AFSNetworkProviderConnectionCB)) { ntStatus = STATUS_INVALID_PARAMETER; break; } ntStatus = AFSCancelConnection( pConnectCB, (AFSCancelConnectionResultCB *)Irp->AssociatedIrp.SystemBuffer, &Irp->IoStatus.Information); break; } case IOCTL_AFS_GET_CONNECTION: { AFSNetworkProviderConnectionCB *pConnectCB = (AFSNetworkProviderConnectionCB *)Irp->AssociatedIrp.SystemBuffer; if( pIrpSp->Parameters.DeviceIoControl.InputBufferLength < sizeof( AFSNetworkProviderConnectionCB) || pIrpSp->Parameters.DeviceIoControl.OutputBufferLength == 0) { ntStatus = STATUS_INVALID_PARAMETER; break; } ntStatus = AFSGetConnection( pConnectCB, (WCHAR *)Irp->AssociatedIrp.SystemBuffer, pIrpSp->Parameters.DeviceIoControl.OutputBufferLength, &Irp->IoStatus.Information); break; } case IOCTL_AFS_LIST_CONNECTIONS: { if( pIrpSp->Parameters.DeviceIoControl.OutputBufferLength == 0) { ntStatus = STATUS_INVALID_PARAMETER; break; } ntStatus = AFSListConnections( (AFSNetworkProviderConnectionCB *)Irp->AssociatedIrp.SystemBuffer, pIrpSp->Parameters.DeviceIoControl.OutputBufferLength, &Irp->IoStatus.Information); break; } case IOCTL_AFS_GET_CONNECTION_INFORMATION: { AFSNetworkProviderConnectionCB *pConnectCB = (AFSNetworkProviderConnectionCB *)Irp->AssociatedIrp.SystemBuffer; if( pIrpSp->Parameters.DeviceIoControl.InputBufferLength < sizeof( AFSNetworkProviderConnectionCB) || pIrpSp->Parameters.DeviceIoControl.OutputBufferLength == 0) { ntStatus = STATUS_INVALID_PARAMETER; break; } ntStatus = AFSGetConnectionInfo( pConnectCB, pIrpSp->Parameters.DeviceIoControl.OutputBufferLength, &Irp->IoStatus.Information); break; } case IOCTL_AFS_SET_FILE_EXTENTS: { AFSSetFileExtentsCB *pExtents = (AFSSetFileExtentsCB*) Irp->AssociatedIrp.SystemBuffer; // // Check lengths twice so that if the buffer makes the // count invalid we will not Accvio // if( pIrpSp->Parameters.DeviceIoControl.InputBufferLength < ( FIELD_OFFSET( AFSSetFileExtentsCB, ExtentCount) + sizeof(ULONG)) || pIrpSp->Parameters.DeviceIoControl.InputBufferLength < ( FIELD_OFFSET( AFSSetFileExtentsCB, ExtentCount) + sizeof(ULONG) + sizeof (AFSFileExtentCB) * pExtents->ExtentCount)) { ntStatus = STATUS_INVALID_PARAMETER; break; } ntStatus = AFSProcessSetFileExtents( pExtents ); Irp->IoStatus.Information = 0; Irp->IoStatus.Status = ntStatus; break; } case IOCTL_AFS_RELEASE_FILE_EXTENTS: { ntStatus = AFSProcessReleaseFileExtents( Irp); break; } case IOCTL_AFS_SET_FILE_EXTENT_FAILURE: { ntStatus = AFSProcessExtentFailure( Irp); break; } case IOCTL_AFS_INVALIDATE_CACHE: { AFSInvalidateCacheCB *pInvalidate = (AFSInvalidateCacheCB*)Irp->AssociatedIrp.SystemBuffer; if( pIrpSp->Parameters.DeviceIoControl.InputBufferLength < sizeof( AFSInvalidateCacheCB)) { ntStatus = STATUS_INVALID_PARAMETER; break; } ntStatus = AFSInvalidateCache( pInvalidate); Irp->IoStatus.Information = 0; Irp->IoStatus.Status = ntStatus; break; } case IOCTL_AFS_NETWORK_STATUS: { AFSNetworkStatusCB *pNetworkStatus = (AFSNetworkStatusCB *)Irp->AssociatedIrp.SystemBuffer; if( pIrpSp->Parameters.DeviceIoControl.InputBufferLength < sizeof( AFSNetworkStatusCB)) { ntStatus = STATUS_INVALID_PARAMETER; break; } // // Set the network status // ntStatus = AFSSetNetworkState( pNetworkStatus); Irp->IoStatus.Information = 0; Irp->IoStatus.Status = ntStatus; break; } case IOCTL_AFS_VOLUME_STATUS: { AFSVolumeStatusCB *pVolumeStatus = (AFSVolumeStatusCB *)Irp->AssociatedIrp.SystemBuffer; if( pIrpSp->Parameters.DeviceIoControl.InputBufferLength < sizeof( AFSVolumeStatusCB)) { ntStatus = STATUS_INVALID_PARAMETER; break; } ntStatus = AFSSetVolumeState( pVolumeStatus); Irp->IoStatus.Information = 0; Irp->IoStatus.Status = ntStatus; break; } case IOCTL_AFS_STATUS_REQUEST: { if( pIrpSp->Parameters.DeviceIoControl.OutputBufferLength < sizeof( AFSDriverStatusRespCB)) { ntStatus = STATUS_INVALID_PARAMETER; break; } ntStatus = AFSGetDriverStatus( (AFSDriverStatusRespCB *)Irp->AssociatedIrp.SystemBuffer); Irp->IoStatus.Information = sizeof( AFSDriverStatusRespCB); break; } case IOCTL_AFS_GET_OBJECT_INFORMATION: { if( pIrpSp->Parameters.DeviceIoControl.InputBufferLength < sizeof( AFSGetStatusInfoCB) || pIrpSp->Parameters.DeviceIoControl.OutputBufferLength < sizeof( AFSStatusInfoCB)) { ntStatus = STATUS_INVALID_PARAMETER; break; } ntStatus = AFSGetObjectStatus( (AFSGetStatusInfoCB *)Irp->AssociatedIrp.SystemBuffer, pIrpSp->Parameters.DeviceIoControl.InputBufferLength, (AFSStatusInfoCB *)Irp->AssociatedIrp.SystemBuffer, (ULONG *)&Irp->IoStatus.Information); break; } case 0x140390: // IOCTL_LMR_DISABLE_LOCAL_BUFFERING { // // See http://msdn.microsoft.com/en-us/library/ee210753%28v=vs.85%29.aspx // // The IOCTL_LMR_DISABLE_LOCAL_BUFFERING control code is defined internally by // the system as 0x140390 and not in a public header file. It is used by // special-purpose applications to disable local client-side in-memory // caching of data when reading data from or writing data to a remote file. // After local buffering is disabled, the setting remains in effect until all // open handles to the file are closed and the redirector cleans up its internal // data structures. // // General-purpose applications should not use IOCTL_LMR_DISABLE_LOCAL_BUFFERING, // because it can result in excessive network traffic and associated loss of // performance. The IOCTL_LMR_DISABLE_LOCAL_BUFFERING control code should be used // only in specialized applications moving large amounts of data over the network // while attempting to maximize use of network bandwidth. For example, the CopyFile // and CopyFileEx functions use IOCTL_LMR_DISABLE_LOCAL_BUFFERING to improve large // file copy performance. // // IOCTL_LMR_DISABLE_LOCAL_BUFFERING is not implemented by local file systems and // will fail with the error ERROR_INVALID_FUNCTION. Issuing the // IOCTL_LMR_DISABLE_LOCAL_BUFFERING control code on remote directory handles will // fail with the error ERROR_NOT_SUPPORTED. // ntStatus = STATUS_NOT_SUPPORTED; break; } default: { ntStatus = STATUS_NOT_IMPLEMENTED; break; } } //try_exit: } __except( AFSExceptionFilter( __FUNCTION__, GetExceptionCode(), GetExceptionInformation())) { ntStatus = STATUS_UNSUCCESSFUL; AFSDumpTraceFilesFnc(); } Irp->IoStatus.Status = ntStatus; AFSCompleteRequest( Irp, ntStatus); return ntStatus; }
NTSTATUS AFSInitRootFcb( IN ULONGLONG ProcessID, IN AFSVolumeCB *VolumeCB) { NTSTATUS ntStatus = STATUS_SUCCESS; AFSFcb *pFcb = NULL; AFSNonPagedFcb *pNPFcb = NULL; IO_STATUS_BLOCK stIoStatus = {0,0}; AFSDeviceExt *pDeviceExt = (AFSDeviceExt *)AFSRDRDeviceObject->DeviceExtension; __Enter { // // Initialize the root fcb // pFcb = (AFSFcb *)AFSExAllocatePoolWithTag( PagedPool, sizeof( AFSFcb), AFS_FCB_ALLOCATION_TAG); if( pFcb == NULL) { AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING, AFS_TRACE_LEVEL_ERROR, "AFSInitRootFcb Failed to allocate the root fcb\n"); try_return( ntStatus = STATUS_INSUFFICIENT_RESOURCES); } RtlZeroMemory( pFcb, sizeof( AFSFcb)); pFcb->Header.NodeByteSize = sizeof( AFSFcb); pFcb->Header.NodeTypeCode = AFS_ROOT_FCB; pNPFcb = (AFSNonPagedFcb *)AFSExAllocatePoolWithTag( NonPagedPool, sizeof( AFSNonPagedFcb), AFS_FCB_NP_ALLOCATION_TAG); if( pNPFcb == NULL) { AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING, AFS_TRACE_LEVEL_ERROR, "AFSInitRootFcb Failed to allocate the non-paged fcb\n"); try_return( ntStatus = STATUS_INSUFFICIENT_RESOURCES); } RtlZeroMemory( pNPFcb, sizeof( AFSNonPagedFcb)); pNPFcb->Size = sizeof( AFSNonPagedFcb); pNPFcb->Type = AFS_NON_PAGED_FCB; // // OK, initialize the entry // ExInitializeFastMutex( &pNPFcb->AdvancedHdrMutex); FsRtlSetupAdvancedHeader( &pFcb->Header, &pNPFcb->AdvancedHdrMutex); ExInitializeResourceLite( &pNPFcb->Resource); AFSDbgLogMsg( AFS_SUBSYSTEM_LOCK_PROCESSING, AFS_TRACE_LEVEL_VERBOSE, "AFSInitRootFcb Acquiring Fcb lock %08lX EXCL %08lX\n", &pNPFcb->Resource, PsGetCurrentThread()); AFSAcquireExcl( &pNPFcb->Resource, TRUE); ExInitializeResourceLite( &pNPFcb->PagingResource); ExInitializeResourceLite( &pNPFcb->CcbListLock); pFcb->Header.Resource = &pNPFcb->Resource; pFcb->Header.PagingIoResource = &pNPFcb->PagingResource; pFcb->NPFcb = pNPFcb; // // Initialize enumeration information // KeInitializeEvent( &pFcb->NPFcb->Specific.Directory.DirectoryEnumEvent, NotificationEvent, FALSE); // // Save the root Fcb in the VolumeCB // VolumeCB->ObjectInformation.Fcb = pFcb; VolumeCB->ObjectInformation.VolumeCB = VolumeCB; VolumeCB->RootFcb = pFcb; pFcb->ObjectInformation = &VolumeCB->ObjectInformation; try_exit: if( !NT_SUCCESS( ntStatus)) { if( pFcb != NULL) { AFSRemoveRootFcb( pFcb); } } } return ntStatus; }
NTSTATUS AFSInitializeRedirector( IN AFSRedirectorInitInfo *RedirInitInfo) { NTSTATUS ntStatus = STATUS_SUCCESS; LARGE_INTEGER cacheSizeBytes; AFSDeviceExt *pDevExt = (AFSDeviceExt *)AFSRDRDeviceObject->DeviceExtension; AFSDeviceExt *pControlDevExt = (AFSDeviceExt *)AFSDeviceObject->DeviceExtension; OBJECT_ATTRIBUTES stObjectAttribs; IO_STATUS_BLOCK stIoStatus; UNICODE_STRING uniServiceName; __Enter { // // First this is to load the library // RtlInitUnicodeString( &uniServiceName, AFS_REDIR_LIBRARY_SERVICE_ENTRY); ntStatus = AFSLoadLibrary( 0, &uniServiceName); if( !NT_SUCCESS( ntStatus)) { AFSDbgLogMsg( AFS_SUBSYSTEM_INIT_PROCESSING, AFS_TRACE_LEVEL_ERROR, "AFSInitializeRedirector AFSLoadLibrary failure %08lX\n", ntStatus); try_return( ntStatus); } // // Save off the cache file information // pDevExt->Specific.RDR.CacheBlockSize = RedirInitInfo->CacheBlockSize; pDevExt->Specific.RDR.CacheBlockCount = RedirInitInfo->ExtentCount; pDevExt->Specific.RDR.MaximumRPCLength = RedirInitInfo->MaximumChunkLength; cacheSizeBytes = RedirInitInfo->ExtentCount; cacheSizeBytes.QuadPart *= RedirInitInfo->CacheBlockSize; AFSDumpFileLocation.Length = 0; AFSDumpFileLocation.MaximumLength = (USHORT)RedirInitInfo->DumpFileLocationLength + (4 * sizeof( WCHAR)); AFSDumpFileLocation.Buffer = (WCHAR *)AFSExAllocatePoolWithTag( PagedPool, AFSDumpFileLocation.MaximumLength, AFS_GENERIC_MEMORY_23_TAG); if( AFSDumpFileLocation.Buffer == NULL) { AFSDbgLogMsg( AFS_SUBSYSTEM_INIT_PROCESSING, AFS_TRACE_LEVEL_ERROR, "AFSInitializeRedirector AFS_GENERIC_MEMORY_23_TAG allocation error\n"); try_return( ntStatus = STATUS_INSUFFICIENT_RESOURCES); } RtlCopyMemory( AFSDumpFileLocation.Buffer, L"\\??\\", 4 * sizeof( WCHAR)); AFSDumpFileLocation.Length = 4 * sizeof( WCHAR); RtlCopyMemory( &AFSDumpFileLocation.Buffer[ AFSDumpFileLocation.Length/sizeof( WCHAR)], (void *)((char *)RedirInitInfo + RedirInitInfo->DumpFileLocationOffset), RedirInitInfo->DumpFileLocationLength); AFSDumpFileLocation.Length += (USHORT)RedirInitInfo->DumpFileLocationLength; // // Be sure the shutdown flag is not set // ClearFlag( pDevExt->DeviceFlags, AFS_DEVICE_FLAG_REDIRECTOR_SHUTDOWN); // // Set up the Throttles. // // Max IO is 10% of the cache, or the value in the registry, // with a minimum of 5Mb (and a maximum of 50% cache size) // if( AFSMaxDirectIo) { // // collect what the user // pDevExt->Specific.RDR.MaxIo.QuadPart = AFSMaxDirectIo; pDevExt->Specific.RDR.MaxIo.QuadPart *= (1024 * 1024); } else { pDevExt->Specific.RDR.MaxIo.QuadPart = cacheSizeBytes.QuadPart / 2; } if (pDevExt->Specific.RDR.MaxIo.QuadPart < (5 * 1024 * 1204)) { pDevExt->Specific.RDR.MaxIo.QuadPart = 5 * 1024 * 1204; } // // For small cache configurations ... // if (pDevExt->Specific.RDR.MaxIo.QuadPart > cacheSizeBytes.QuadPart / 2) { pDevExt->Specific.RDR.MaxIo.QuadPart = cacheSizeBytes.QuadPart / 2; } // // Maximum Dirty is 50% of the cache, or the value in the // registry. No minimum, maximum of 90% of cache size. // if (AFSMaxDirtyFile) { pDevExt->Specific.RDR.MaxDirty.QuadPart = AFSMaxDirtyFile; pDevExt->Specific.RDR.MaxDirty.QuadPart *= (1024 * 1024); } else { pDevExt->Specific.RDR.MaxDirty.QuadPart = cacheSizeBytes.QuadPart/2; } cacheSizeBytes.QuadPart *= 9; cacheSizeBytes.QuadPart = cacheSizeBytes.QuadPart / 10; if (pDevExt->Specific.RDR.MaxDirty.QuadPart > cacheSizeBytes.QuadPart) { pDevExt->Specific.RDR.MaxDirty.QuadPart = cacheSizeBytes.QuadPart; } // // Store off any flags for the file system // if( BooleanFlagOn( RedirInitInfo->Flags, AFS_REDIR_INIT_FLAG_HIDE_DOT_FILES)) { // // Hide files which begin with . // SetFlag( pDevExt->DeviceFlags, AFS_DEVICE_FLAG_HIDE_DOT_NAMES); } if( RedirInitInfo->MemoryCacheOffset.QuadPart != 0 && RedirInitInfo->MemoryCacheLength.QuadPart != 0) { ntStatus = STATUS_INSUFFICIENT_RESOURCES; #ifdef AMD64 pDevExt->Specific.RDR.CacheMdl = MmCreateMdl( NULL, (void *)RedirInitInfo->MemoryCacheOffset.QuadPart, RedirInitInfo->MemoryCacheLength.QuadPart); #else pDevExt->Specific.RDR.CacheMdl = MmCreateMdl( NULL, (void *)RedirInitInfo->MemoryCacheOffset.LowPart, RedirInitInfo->MemoryCacheLength.LowPart); #endif if( pDevExt->Specific.RDR.CacheMdl != NULL) { __try { MmProbeAndLockPages( pDevExt->Specific.RDR.CacheMdl, KernelMode, IoModifyAccess); pDevExt->Specific.RDR.CacheBaseAddress = MmGetSystemAddressForMdlSafe( pDevExt->Specific.RDR.CacheMdl, NormalPagePriority); } __except( AFSExceptionFilter( GetExceptionCode(), GetExceptionInformation()) ) { IoFreeMdl( pDevExt->Specific.RDR.CacheMdl); pDevExt->Specific.RDR.CacheMdl = NULL; } if( pDevExt->Specific.RDR.CacheMdl != NULL) { pDevExt->Specific.RDR.CacheLength = RedirInitInfo->MemoryCacheLength; ntStatus = STATUS_SUCCESS; } } }
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 AFSProcessIrpResult( IN PIRP Irp) { NTSTATUS ntStatus = STATUS_SUCCESS; AFSDeviceExt *pDevExt = (AFSDeviceExt *)AFSDeviceObject->DeviceExtension; IO_STACK_LOCATION *pIrpSp = IoGetCurrentIrpStackLocation( Irp); AFSCommSrvcCB *pCommSrvc = NULL; AFSPoolEntry *pCurrentEntry = NULL; AFSCommResult *pResult = NULL; ULONG ulCopyLen = 0; __Enter { pCommSrvc = &pDevExt->Specific.Control.CommServiceCB; // // Get the request for the incoming result // pResult = (AFSCommResult *)Irp->AssociatedIrp.SystemBuffer; if( pResult == NULL) { try_return( ntStatus = STATUS_INVALID_PARAMETER); } // // Go look for our entry // AFSDbgLogMsg( AFS_SUBSYSTEM_LOCK_PROCESSING, AFS_TRACE_LEVEL_VERBOSE, "AFSProcessIrpResult Acquiring ResultPoolLock lock %08lX EXCL %08lX\n", &pCommSrvc->ResultPoolLock, PsGetCurrentThread()); AFSAcquireExcl( &pCommSrvc->ResultPoolLock, TRUE); pCurrentEntry = pCommSrvc->ResultPoolHead; while( pCurrentEntry != NULL) { if( pCurrentEntry->RequestIndex == pResult->RequestIndex) { // // Found the entry so remove it from the queue // if( pCurrentEntry->bLink == NULL) { // // At the head of the list // pCommSrvc->ResultPoolHead = pCurrentEntry->fLink; if( pCommSrvc->ResultPoolHead != NULL) { pCommSrvc->ResultPoolHead->bLink = NULL; } } else { pCurrentEntry->bLink->fLink = pCurrentEntry->fLink; } if( pCurrentEntry->fLink == NULL) { pCommSrvc->ResultPoolTail = pCurrentEntry->bLink; if( pCommSrvc->ResultPoolTail != NULL) { pCommSrvc->ResultPoolTail->fLink = NULL; } } else { pCurrentEntry->fLink->bLink = pCurrentEntry->bLink; } break; } pCurrentEntry = pCurrentEntry->fLink; } AFSReleaseResource( &pCommSrvc->ResultPoolLock); if( pCurrentEntry == NULL) { try_return( ntStatus = STATUS_INVALID_PARAMETER); } // // OK, move in the result information // pCurrentEntry->ResultStatus = pResult->ResultStatus; if( ( pCurrentEntry->ResultStatus == STATUS_SUCCESS || pCurrentEntry->ResultStatus == STATUS_BUFFER_OVERFLOW) && pCurrentEntry->ResultBufferLength != NULL && pCurrentEntry->ResultBuffer != NULL) { ASSERT( pResult->ResultBufferLength <= *(pCurrentEntry->ResultBufferLength)); ulCopyLen = pResult->ResultBufferLength; if( ulCopyLen > *(pCurrentEntry->ResultBufferLength)) { ulCopyLen = *(pCurrentEntry->ResultBufferLength); } *(pCurrentEntry->ResultBufferLength) = ulCopyLen; if( pResult->ResultBufferLength > 0) { RtlCopyMemory( pCurrentEntry->ResultBuffer, pResult->ResultData, ulCopyLen); } } KeSetEvent( &pCurrentEntry->Event, 0, FALSE); try_exit: if( !NT_SUCCESS( ntStatus)) { } } return ntStatus; }