NTSTATUS AFSInsertCcb( IN AFSFcb *Fcb, IN AFSCcb *Ccb) { NTSTATUS ntStatus = STATUS_SUCCESS; AFSAcquireExcl( &Fcb->NPFcb->CcbListLock, TRUE); if( Fcb->CcbListHead == NULL) { Fcb->CcbListHead = Ccb; } else { Fcb->CcbListTail->ListEntry.fLink = (void *)Ccb; Ccb->ListEntry.bLink = (void *)Fcb->CcbListTail; } Fcb->CcbListTail = Ccb; SetFlag( Ccb->Flags, CCB_FLAG_INSERTED_CCB_LIST); AFSReleaseResource( &Fcb->NPFcb->CcbListLock); return ntStatus; }
NTSTATUS AFSTearDownDbgLog() { NTSTATUS ntStatus = STATUS_SUCCESS; AFSAcquireExcl( &AFSDbgLogLock, TRUE); if( AFSDbgBuffer != NULL) { ExFreePool( AFSDbgBuffer); } AFSDbgBuffer = NULL; AFSDbgCurrentBuffer = NULL; AFSDbgLogRemainingLength = 0; AFSReleaseResource( &AFSDbgLogLock); return ntStatus; }
NTSTATUS AFSInitializeDbgLog() { NTSTATUS ntStatus = STATUS_INSUFFICIENT_RESOURCES; AFSAcquireExcl( &AFSDbgLogLock, TRUE); if( AFSDbgBufferLength > 0) { AFSDbgBuffer = (char *)AFSExAllocatePoolWithTag( NonPagedPool, AFSDbgBufferLength, AFS_GENERIC_MEMORY_19_TAG); if( AFSDbgBuffer != NULL) { AFSDbgCurrentBuffer = AFSDbgBuffer; AFSDbgLogRemainingLength = AFSDbgBufferLength; ntStatus = STATUS_SUCCESS; } } AFSReleaseResource( &AFSDbgLogLock); if( NT_SUCCESS( ntStatus)) { AFSTagInitialLogEntry(); } 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 AFSLoadLibrary( IN ULONG Flags, IN UNICODE_STRING *ServicePath) { UNREFERENCED_PARAMETER(Flags); NTSTATUS ntStatus = STATUS_SUCCESS; AFSDeviceExt *pDevExt = (AFSDeviceExt *)AFSDeviceObject->DeviceExtension; UNICODE_STRING uniLibraryName; AFSDeviceExt *pLibDevExt = NULL; PFILE_OBJECT pLibraryFileObject = NULL; PDEVICE_OBJECT pLibraryDeviceObject = NULL; __Enter { // // Wait on the load library event so we don't race with any // other requests coming through // AFSDbgTrace(( AFS_SUBSYSTEM_LOAD_LIBRARY, AFS_TRACE_LEVEL_VERBOSE, "%s Start load library\n", __FUNCTION__)); ntStatus = KeWaitForSingleObject( &pDevExt->Specific.Control.LoadLibraryEvent, Executive, KernelMode, FALSE, NULL); if( !NT_SUCCESS( ntStatus)) { AFSDbgTrace(( AFS_SUBSYSTEM_LOAD_LIBRARY | AFS_SUBSYSTEM_INIT_PROCESSING, AFS_TRACE_LEVEL_ERROR, "AFSLoadLibrary Wait for LoadLibraryEvent failure %08lX\n", ntStatus)); try_return( ntStatus); } // // Check our current state to ensure we currently do not have a library loaded // if( BooleanFlagOn( pDevExt->Specific.Control.LibraryState, AFS_LIBRARY_LOADED)) { AFSDbgTrace(( AFS_SUBSYSTEM_LOAD_LIBRARY | AFS_SUBSYSTEM_INIT_PROCESSING, AFS_TRACE_LEVEL_VERBOSE, "%s Library already loaded\n", __FUNCTION__)); try_return( ntStatus = STATUS_DEVICE_NOT_READY); } pDevExt->Specific.Control.LibraryServicePath.Buffer = (WCHAR *)AFSExAllocatePoolWithTag( PagedPool, ServicePath->Length, AFS_GENERIC_MEMORY_25_TAG); if( pDevExt->Specific.Control.LibraryServicePath.Buffer == NULL) { AFSDbgTrace(( AFS_SUBSYSTEM_LOAD_LIBRARY | AFS_SUBSYSTEM_INIT_PROCESSING, AFS_TRACE_LEVEL_ERROR, "AFSLoadLibrary AFS_GENERIC_MEMORY_25_TAG allocation error\n")); try_return( ntStatus = STATUS_INSUFFICIENT_RESOURCES); } RtlZeroMemory( pDevExt->Specific.Control.LibraryServicePath.Buffer, ServicePath->Length); pDevExt->Specific.Control.LibraryServicePath.Length = ServicePath->Length; pDevExt->Specific.Control.LibraryServicePath.MaximumLength = pDevExt->Specific.Control.LibraryServicePath.Length; RtlCopyMemory( pDevExt->Specific.Control.LibraryServicePath.Buffer, ServicePath->Buffer, pDevExt->Specific.Control.LibraryServicePath.Length); // // Load the library // ntStatus = ZwLoadDriver( ServicePath); if( !NT_SUCCESS( ntStatus)) { AFSDbgTrace(( AFS_SUBSYSTEM_LOAD_LIBRARY | AFS_SUBSYSTEM_INIT_PROCESSING, AFS_TRACE_LEVEL_ERROR, "%s Failed to load library Status %08lX\n", __FUNCTION__, ntStatus)); try_return( ntStatus); } // // Open up the control device and grab teh entry points for the library // RtlInitUnicodeString( &uniLibraryName, AFS_LIBRARY_CONTROL_DEVICE_NAME); ntStatus = IoGetDeviceObjectPointer( &uniLibraryName, FILE_ALL_ACCESS, &pLibraryFileObject, &pLibraryDeviceObject); if( !NT_SUCCESS( ntStatus)) { AFSDbgTrace(( AFS_SUBSYSTEM_LOAD_LIBRARY | AFS_SUBSYSTEM_INIT_PROCESSING, AFS_TRACE_LEVEL_ERROR, "AFSLoadLibrary IoGetDeviceObjectPointer failure %08lX\n", ntStatus)); try_return( ntStatus); } // // We have our reference to the library device object. Grab the // device extension and setup our callbacks // pLibDevExt = (AFSDeviceExt *)pLibraryDeviceObject->DeviceExtension; // // Save off our references // pDevExt->Specific.Control.LibraryFileObject = pLibraryFileObject; pDevExt->Specific.Control.LibraryDeviceObject = pLibraryDeviceObject; // // Reset the state for our library // AFSAcquireExcl( &pDevExt->Specific.Control.LibraryStateLock, TRUE); SetFlag( pDevExt->Specific.Control.LibraryState, AFS_LIBRARY_LOADED); ClearFlag( pDevExt->Specific.Control.LibraryState, AFS_LIBRARY_QUEUE_CANCELLED); AFSDbgTrace(( AFS_SUBSYSTEM_LOAD_LIBRARY | AFS_SUBSYSTEM_INIT_PROCESSING, AFS_TRACE_LEVEL_VERBOSE, "%s Completed load library, processing queued requests\n", __FUNCTION__)); AFSReleaseResource( &pDevExt->Specific.Control.LibraryStateLock); // // Process the queued requests // AFSProcessQueuedResults( FALSE); try_exit: AFSDbgTrace(( AFS_SUBSYSTEM_LOAD_LIBRARY | AFS_SUBSYSTEM_INIT_PROCESSING, AFS_TRACE_LEVEL_VERBOSE, "%s Library load complete Status %08lX\n", __FUNCTION__, ntStatus)); if( !NT_SUCCESS( ntStatus)) { if( pDevExt->Specific.Control.LibraryServicePath.Buffer != NULL) { ZwUnloadDriver( &pDevExt->Specific.Control.LibraryServicePath); ExFreePool( pDevExt->Specific.Control.LibraryServicePath.Buffer); pDevExt->Specific.Control.LibraryServicePath.Buffer = NULL; pDevExt->Specific.Control.LibraryServicePath.Length = 0; pDevExt->Specific.Control.LibraryServicePath.MaximumLength = 0; } } KeSetEvent( &pDevExt->Specific.Control.LoadLibraryEvent, 0, FALSE); } 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 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 AFSConfigureTrace( IN AFSTraceConfigCB *TraceInfo) { NTSTATUS ntStatus = STATUS_SUCCESS; UNICODE_STRING uniString; __Enter { AFSAcquireExcl( &AFSDbgLogLock, TRUE); if( TraceInfo->TraceLevel == AFSTraceLevel && TraceInfo->TraceBufferLength == AFSDbgBufferLength && TraceInfo->Subsystem == AFSTraceComponent) { // // Nothing to do // try_return( ntStatus); } // // Go update the registry with the new entries // if( TraceInfo->TraceLevel != (ULONG)-1 && TraceInfo->TraceLevel != AFSTraceLevel) { AFSTraceLevel = TraceInfo->TraceLevel; RtlInitUnicodeString( &uniString, AFS_REG_TRACE_LEVEL); ntStatus = AFSUpdateRegistryParameter( &uniString, REG_DWORD, &TraceInfo->TraceLevel, sizeof( ULONG)); if( !NT_SUCCESS( ntStatus)) { DbgPrint("AFSConfigureTrace Failed to set debug level in registry Status %08lX\n", ntStatus); } } if( TraceInfo->Subsystem != (ULONG)-1 && TraceInfo->Subsystem != AFSTraceComponent) { AFSTraceComponent = TraceInfo->Subsystem; RtlInitUnicodeString( &uniString, AFS_REG_TRACE_SUBSYSTEM); ntStatus = AFSUpdateRegistryParameter( &uniString, REG_DWORD, &TraceInfo->Subsystem, sizeof( ULONG)); if( !NT_SUCCESS( ntStatus)) { DbgPrint("AFSConfigureTrace Failed to set debug subsystem in registry Status %08lX\n", ntStatus); } } if( TraceInfo->DebugFlags != (ULONG)-1 && TraceInfo->DebugFlags != AFSDebugFlags) { AFSDebugFlags = TraceInfo->DebugFlags; RtlInitUnicodeString( &uniString, AFS_REG_DEBUG_FLAGS); ntStatus = AFSUpdateRegistryParameter( &uniString, REG_DWORD, &TraceInfo->DebugFlags, sizeof( ULONG)); if( !NT_SUCCESS( ntStatus)) { DbgPrint("AFSConfigureTrace Failed to set debug flags in registry Status %08lX\n", ntStatus); } } if( TraceInfo->TraceBufferLength != (ULONG)-1 && TraceInfo->TraceBufferLength != AFSDbgBufferLength) { RtlInitUnicodeString( &uniString, AFS_REG_TRACE_BUFFER_LENGTH); ntStatus = AFSUpdateRegistryParameter( &uniString, REG_DWORD, &TraceInfo->TraceBufferLength, sizeof( ULONG)); if( !NT_SUCCESS( ntStatus)) { DbgPrint("AFSConfigureTrace Failed to set debug buffer length in registry Status %08lX\n", ntStatus); } AFSDbgBufferLength = TraceInfo->TraceBufferLength * 1024; ClearFlag( AFSDbgLogFlags, AFS_DBG_LOG_WRAPPED); if( AFSDbgBuffer != NULL) { ExFreePool( AFSDbgBuffer); AFSDbgBuffer = NULL; AFSDbgCurrentBuffer = NULL; AFSDbgLogRemainingLength = 0; } if( AFSDbgBufferLength > 0) { AFSDbgBuffer = (char *)AFSExAllocatePoolWithTag( NonPagedPool, AFSDbgBufferLength, AFS_GENERIC_MEMORY_20_TAG); if( AFSDbgBuffer == NULL) { AFSDbgBufferLength = 0; try_return( ntStatus = STATUS_INSUFFICIENT_RESOURCES); } AFSDbgCurrentBuffer = AFSDbgBuffer; AFSDbgLogRemainingLength = AFSDbgBufferLength; AFSTagInitialLogEntry(); } } try_exit: AFSReleaseResource( &AFSDbgLogLock); } 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 AFSProcessUserFsRequest( IN PIRP Irp) { NTSTATUS ntStatus = STATUS_SUCCESS; ULONG ulFsControlCode; AFSFcb *pFcb = NULL; PIO_STACK_LOCATION pIrpSp = IoGetCurrentIrpStackLocation( Irp ); AFSCcb *pCcb = NULL; ULONG ulOutputBufferLen, ulInputBufferLen; __Enter { ulFsControlCode = pIrpSp->Parameters.FileSystemControl.FsControlCode; pFcb = (AFSFcb *)pIrpSp->FileObject->FsContext; pCcb = (AFSCcb *)pIrpSp->FileObject->FsContext2; if( pFcb == NULL || pCcb == NULL || pCcb->DirectoryCB == NULL) { AFSDbgTrace(( AFS_SUBSYSTEM_FILE_PROCESSING, AFS_TRACE_LEVEL_VERBOSE_2, "AFSProcessUserFsRequest Invalid Fcb\n")); try_return( ntStatus = STATUS_INVALID_DEVICE_REQUEST); } if( pFcb->Header.NodeTypeCode == AFS_SPECIAL_SHARE_FCB) { ntStatus = AFSProcessShareFsCtrl( Irp, pFcb, pCcb); try_return( ntStatus); } ulOutputBufferLen = pIrpSp->Parameters.FileSystemControl.OutputBufferLength; ulInputBufferLen = pIrpSp->Parameters.FileSystemControl.InputBufferLength; // // Process the request // switch( ulFsControlCode ) { case FSCTL_REQUEST_OPLOCK_LEVEL_1: case FSCTL_REQUEST_OPLOCK_LEVEL_2: case FSCTL_REQUEST_BATCH_OPLOCK: case FSCTL_OPLOCK_BREAK_ACKNOWLEDGE: case FSCTL_OPBATCH_ACK_CLOSE_PENDING: case FSCTL_OPLOCK_BREAK_NOTIFY: case FSCTL_OPLOCK_BREAK_ACK_NO_2: case FSCTL_REQUEST_FILTER_OPLOCK : { // // Note that implementing this call will probably need us // to call the server as well as adding code in read and // write and caching. Also that it is unlikely that // anyone will ever call us at this point - RDR doesn't // allow it // ntStatus = STATUS_NOT_IMPLEMENTED; break; } case FSCTL_LOCK_VOLUME: { AFSDbgTrace(( AFS_SUBSYSTEM_FILE_PROCESSING, AFS_TRACE_LEVEL_VERBOSE_2, "AFSProcessUserFsRequest Processing FSCTL_LOCK_VOLUME request\n")); ntStatus = STATUS_NOT_IMPLEMENTED; break; } case FSCTL_UNLOCK_VOLUME: { AFSDbgTrace(( AFS_SUBSYSTEM_FILE_PROCESSING, AFS_TRACE_LEVEL_VERBOSE_2, "AFSProcessUserFsRequest Processing FSCTL_UNLOCK_VOLUME request\n")); ntStatus = STATUS_NOT_IMPLEMENTED; break; } case FSCTL_DISMOUNT_VOLUME: { AFSDbgTrace(( AFS_SUBSYSTEM_FILE_PROCESSING, AFS_TRACE_LEVEL_VERBOSE_2, "AFSProcessUserFsRequest Processing FSCTL_DISMOUNT_VOLUME request\n")); ntStatus = STATUS_NOT_IMPLEMENTED; break; } case FSCTL_MARK_VOLUME_DIRTY: { AFSDbgTrace(( AFS_SUBSYSTEM_FILE_PROCESSING, AFS_TRACE_LEVEL_VERBOSE_2, "AFSProcessUserFsRequest Processing FSCTL_MARK_VOLUME_DIRTY request\n")); ntStatus = STATUS_NOT_IMPLEMENTED; break; } case FSCTL_IS_VOLUME_DIRTY: { AFSDbgTrace(( AFS_SUBSYSTEM_FILE_PROCESSING, AFS_TRACE_LEVEL_VERBOSE_2, "AFSProcessUserFsRequest Processing FSCTL_IS_VOLUME_DIRTY request\n")); ntStatus = STATUS_NOT_IMPLEMENTED; break; } case FSCTL_IS_VOLUME_MOUNTED: { AFSDbgTrace(( AFS_SUBSYSTEM_FILE_PROCESSING, AFS_TRACE_LEVEL_VERBOSE_2, "AFSProcessUserFsRequest Processing FSCTL_IS_VOLUME_MOUNTED request\n")); ntStatus = STATUS_NOT_IMPLEMENTED; break; } case FSCTL_IS_PATHNAME_VALID: { AFSDbgTrace(( AFS_SUBSYSTEM_FILE_PROCESSING, AFS_TRACE_LEVEL_VERBOSE_2, "AFSProcessUserFsRequest Processing FSCTL_IS_PATHNAME_VALID request\n")); ntStatus = STATUS_SUCCESS; break; } #ifndef FSCTL_CSC_INTERNAL #define FSCTL_CSC_INTERNAL CTL_CODE(FILE_DEVICE_FILE_SYSTEM, 107, METHOD_NEITHER, FILE_ANY_ACCESS) #endif case FSCTL_CSC_INTERNAL: { AFSDbgTrace(( AFS_SUBSYSTEM_FILE_PROCESSING, AFS_TRACE_LEVEL_VERBOSE_2, "AFSProcessUserFsRequest Processing FSCTL_CSC_INTERNAL request\n")); ntStatus = STATUS_INVALID_DEVICE_REQUEST; break; } case FSCTL_GET_REPARSE_POINT: { REPARSE_GUID_DATA_BUFFER *pReparseBuffer = (REPARSE_GUID_DATA_BUFFER *)Irp->AssociatedIrp.SystemBuffer; REPARSE_DATA_BUFFER *pMSFTReparseBuffer = (REPARSE_DATA_BUFFER *)Irp->AssociatedIrp.SystemBuffer; ULONG ulRemainingLen = ulOutputBufferLen; AFSReparseTagInfo *pReparseInfo = NULL; BOOLEAN bRelative = FALSE; BOOLEAN bDriveLetter = FALSE; WCHAR * PathBuffer = NULL; AFSDbgTrace(( AFS_SUBSYSTEM_FILE_PROCESSING, AFS_TRACE_LEVEL_VERBOSE_2, "AFSProcessUserFsRequest Processing FSCTL_GET_REPARSE_POINT request %wZ Type 0x%x Attrib 0x%x\n", &pCcb->DirectoryCB->NameInformation.FileName, pFcb->ObjectInformation->FileType, pFcb->ObjectInformation->FileAttributes)); // // Check if we have the reparse entry set on the entry // if( !BooleanFlagOn( pFcb->ObjectInformation->FileAttributes, FILE_ATTRIBUTE_REPARSE_POINT)) { ntStatus = STATUS_NOT_A_REPARSE_POINT; break; } switch ( pFcb->ObjectInformation->FileType) { case AFS_FILE_TYPE_MOUNTPOINT: if( ulOutputBufferLen < FIELD_OFFSET( REPARSE_GUID_DATA_BUFFER, GenericReparseBuffer.DataBuffer)) { ntStatus = STATUS_BUFFER_TOO_SMALL; Irp->IoStatus.Information = FIELD_OFFSET( REPARSE_GUID_DATA_BUFFER, GenericReparseBuffer.DataBuffer); break; } ulRemainingLen -= FIELD_OFFSET( REPARSE_GUID_DATA_BUFFER, GenericReparseBuffer.DataBuffer); break; default: if( ulOutputBufferLen < FIELD_OFFSET( REPARSE_DATA_BUFFER, GenericReparseBuffer.DataBuffer)) { ntStatus = STATUS_BUFFER_TOO_SMALL; Irp->IoStatus.Information = FIELD_OFFSET( REPARSE_DATA_BUFFER, GenericReparseBuffer.DataBuffer); break; } ulRemainingLen -= FIELD_OFFSET( REPARSE_DATA_BUFFER, GenericReparseBuffer.DataBuffer); break; } // // Populate the data in the reparse buffer // pReparseBuffer->ReparseDataLength = 0; AFSAcquireExcl( &pCcb->DirectoryCB->NonPaged->Lock, TRUE); if( pCcb->DirectoryCB->NameInformation.TargetName.Length == 0) { // // We'll reset the DV to ensure we validate the metadata content // pFcb->ObjectInformation->DataVersion.QuadPart = (ULONGLONG)-1; SetFlag( pFcb->ObjectInformation->Flags, AFS_OBJECT_FLAGS_VERIFY); AFSDbgTrace(( AFS_SUBSYSTEM_FILE_PROCESSING, AFS_TRACE_LEVEL_VERBOSE, "AFSProcessUserFsRequest Verifying symlink %wZ FID %08lX-%08lX-%08lX-%08lX\n", &pCcb->DirectoryCB->NameInformation.FileName, pFcb->ObjectInformation->FileId.Cell, pFcb->ObjectInformation->FileId.Volume, pFcb->ObjectInformation->FileId.Vnode, pFcb->ObjectInformation->FileId.Unique)); ntStatus = AFSVerifyEntry( &pCcb->AuthGroup, pCcb->DirectoryCB, FALSE); if( !NT_SUCCESS( ntStatus)) { AFSDbgTrace(( AFS_SUBSYSTEM_FILE_PROCESSING, AFS_TRACE_LEVEL_ERROR, "AFSProcessUserFsRequest Failed to verify symlink %wZ FID %08lX-%08lX-%08lX-%08lX Status %08lX\n", &pCcb->DirectoryCB->NameInformation.FileName, pFcb->ObjectInformation->FileId.Cell, pFcb->ObjectInformation->FileId.Volume, pFcb->ObjectInformation->FileId.Vnode, pFcb->ObjectInformation->FileId.Unique, ntStatus)); AFSReleaseResource( &pCcb->DirectoryCB->NonPaged->Lock); break; } } pReparseInfo = (AFSReparseTagInfo *)&pReparseBuffer->GenericReparseBuffer.DataBuffer[ 0]; switch( pFcb->ObjectInformation->FileType) { case AFS_FILE_TYPE_SYMLINK: { if( pCcb->DirectoryCB->NameInformation.TargetName.Length == 0) { ntStatus = STATUS_REPARSE_POINT_NOT_RESOLVED; break; } bRelative = AFSIsRelativeName( &pCcb->DirectoryCB->NameInformation.TargetName); if ( bRelative) { if( ulRemainingLen < (ULONG) FIELD_OFFSET( REPARSE_DATA_BUFFER, SymbolicLinkReparseBuffer.PathBuffer) + pCcb->DirectoryCB->NameInformation.TargetName.Length) { ntStatus = STATUS_BUFFER_TOO_SMALL; Irp->IoStatus.Information = FIELD_OFFSET( REPARSE_DATA_BUFFER, SymbolicLinkReparseBuffer.PathBuffer) + pCcb->DirectoryCB->NameInformation.TargetName.Length; break; } pMSFTReparseBuffer->SymbolicLinkReparseBuffer.Flags = SYMLINK_FLAG_RELATIVE; pMSFTReparseBuffer->SymbolicLinkReparseBuffer.SubstituteNameLength = pCcb->DirectoryCB->NameInformation.TargetName.Length; pMSFTReparseBuffer->SymbolicLinkReparseBuffer.PrintNameLength = pCcb->DirectoryCB->NameInformation.TargetName.Length; pMSFTReparseBuffer->SymbolicLinkReparseBuffer.SubstituteNameOffset = 0; pMSFTReparseBuffer->SymbolicLinkReparseBuffer.PrintNameOffset = 0; PathBuffer = pMSFTReparseBuffer->SymbolicLinkReparseBuffer.PathBuffer; RtlCopyMemory( PathBuffer, pCcb->DirectoryCB->NameInformation.TargetName.Buffer, pCcb->DirectoryCB->NameInformation.TargetName.Length); pReparseBuffer->ReparseDataLength = FIELD_OFFSET( REPARSE_DATA_BUFFER, SymbolicLinkReparseBuffer.PathBuffer) - FIELD_OFFSET( REPARSE_DATA_BUFFER, GenericReparseBuffer.DataBuffer) + pMSFTReparseBuffer->SymbolicLinkReparseBuffer.SubstituteNameLength; } else { if( ulRemainingLen < (ULONG) FIELD_OFFSET( REPARSE_DATA_BUFFER, SymbolicLinkReparseBuffer.PathBuffer) + /* Display Name */ pCcb->DirectoryCB->NameInformation.TargetName.Length + 1 * sizeof( WCHAR) + /* Substitute Name */ pCcb->DirectoryCB->NameInformation.TargetName.Length + 7 * sizeof( WCHAR)) { ntStatus = STATUS_BUFFER_TOO_SMALL; Irp->IoStatus.Information = FIELD_OFFSET( REPARSE_DATA_BUFFER, SymbolicLinkReparseBuffer.PathBuffer) + pCcb->DirectoryCB->NameInformation.TargetName.Length + 1 * sizeof( WCHAR) + pCcb->DirectoryCB->NameInformation.TargetName.Length + 7 * sizeof( WCHAR); break; } pMSFTReparseBuffer->SymbolicLinkReparseBuffer.Flags = 0; pMSFTReparseBuffer->SymbolicLinkReparseBuffer.SubstituteNameLength = pCcb->DirectoryCB->NameInformation.TargetName.Length + 7 * sizeof( WCHAR); pMSFTReparseBuffer->SymbolicLinkReparseBuffer.PrintNameLength = pCcb->DirectoryCB->NameInformation.TargetName.Length + 1 * sizeof( WCHAR); pMSFTReparseBuffer->SymbolicLinkReparseBuffer.SubstituteNameOffset = pMSFTReparseBuffer->SymbolicLinkReparseBuffer.PrintNameLength; pMSFTReparseBuffer->SymbolicLinkReparseBuffer.PrintNameOffset = 0; PathBuffer = pMSFTReparseBuffer->SymbolicLinkReparseBuffer.PathBuffer; /* Display Name */ *PathBuffer++ = L'\\'; RtlCopyMemory( PathBuffer, pCcb->DirectoryCB->NameInformation.TargetName.Buffer, pCcb->DirectoryCB->NameInformation.TargetName.Length); PathBuffer += pCcb->DirectoryCB->NameInformation.TargetName.Length / sizeof( WCHAR); /* Substitute Name */ *PathBuffer++ = L'\\'; *PathBuffer++ = L'?'; *PathBuffer++ = L'?'; *PathBuffer++ = L'\\'; *PathBuffer++ = L'U'; *PathBuffer++ = L'N'; *PathBuffer++ = L'C'; RtlCopyMemory( PathBuffer, pCcb->DirectoryCB->NameInformation.TargetName.Buffer, pCcb->DirectoryCB->NameInformation.TargetName.Length); pReparseBuffer->ReparseDataLength = FIELD_OFFSET( REPARSE_DATA_BUFFER, SymbolicLinkReparseBuffer.PathBuffer) - FIELD_OFFSET( REPARSE_DATA_BUFFER, GenericReparseBuffer.DataBuffer) + pMSFTReparseBuffer->SymbolicLinkReparseBuffer.PrintNameLength + pMSFTReparseBuffer->SymbolicLinkReparseBuffer.SubstituteNameLength; } break; } case AFS_FILE_TYPE_MOUNTPOINT: { UNICODE_STRING Cell, Volume; USHORT Type; if( pCcb->DirectoryCB->NameInformation.TargetName.Length == 0) { ntStatus = STATUS_REPARSE_POINT_NOT_RESOLVED; break; } if ( !AFSParseMountPointTarget( &pCcb->DirectoryCB->NameInformation.TargetName, &Type, &Volume, &Cell)) { ntStatus = STATUS_INVALID_PARAMETER; break; } if( ulRemainingLen < (ULONG) FIELD_OFFSET( AFSReparseTagInfo, AFSMountPoint.Buffer) + Volume.Length + Cell.Length) { ntStatus = STATUS_BUFFER_TOO_SMALL; Irp->IoStatus.Information = FIELD_OFFSET( REPARSE_GUID_DATA_BUFFER, GenericReparseBuffer.DataBuffer) + FIELD_OFFSET( AFSReparseTagInfo, AFSMountPoint.Buffer) + Volume.Length + Cell.Length; break; } pReparseInfo->SubTag = OPENAFS_SUBTAG_MOUNTPOINT; pReparseInfo->AFSMountPoint.Type = Type; pReparseInfo->AFSMountPoint.MountPointCellLength = Cell.Length; pReparseInfo->AFSMountPoint.MountPointVolumeLength = Volume.Length; RtlCopyMemory( pReparseInfo->AFSMountPoint.Buffer, Cell.Buffer, Cell.Length); RtlCopyMemory( &pReparseInfo->AFSMountPoint.Buffer[ Cell.Length / sizeof( WCHAR)], Volume.Buffer, Volume.Length); pReparseBuffer->ReparseDataLength = (FIELD_OFFSET( AFSReparseTagInfo, AFSMountPoint.Buffer) + Volume.Length + Cell.Length); break; } case AFS_FILE_TYPE_DFSLINK: { if( pCcb->DirectoryCB->NameInformation.TargetName.Length == 0) { ntStatus = STATUS_REPARSE_POINT_NOT_RESOLVED; break; } bRelative = ( pCcb->DirectoryCB->NameInformation.TargetName.Buffer[0] == L'\\'); bDriveLetter = (bRelative == FALSE && pCcb->DirectoryCB->NameInformation.TargetName.Buffer[1] == L':'); if ( bRelative) { if( ulRemainingLen < (ULONG) FIELD_OFFSET( REPARSE_DATA_BUFFER, SymbolicLinkReparseBuffer.PathBuffer) + pCcb->DirectoryCB->NameInformation.TargetName.Length) { ntStatus = STATUS_BUFFER_TOO_SMALL; Irp->IoStatus.Information = FIELD_OFFSET( REPARSE_DATA_BUFFER, SymbolicLinkReparseBuffer.PathBuffer) + pCcb->DirectoryCB->NameInformation.TargetName.Length; break; } pMSFTReparseBuffer->SymbolicLinkReparseBuffer.Flags = SYMLINK_FLAG_RELATIVE; pMSFTReparseBuffer->SymbolicLinkReparseBuffer.SubstituteNameLength = pCcb->DirectoryCB->NameInformation.TargetName.Length; pMSFTReparseBuffer->SymbolicLinkReparseBuffer.PrintNameLength = pCcb->DirectoryCB->NameInformation.TargetName.Length; pMSFTReparseBuffer->SymbolicLinkReparseBuffer.SubstituteNameOffset = 0; pMSFTReparseBuffer->SymbolicLinkReparseBuffer.PrintNameOffset = 0; PathBuffer = pMSFTReparseBuffer->SymbolicLinkReparseBuffer.PathBuffer; RtlCopyMemory( PathBuffer, pCcb->DirectoryCB->NameInformation.TargetName.Buffer, pCcb->DirectoryCB->NameInformation.TargetName.Length); pReparseBuffer->ReparseDataLength = FIELD_OFFSET( REPARSE_DATA_BUFFER, SymbolicLinkReparseBuffer.PathBuffer) - FIELD_OFFSET( REPARSE_DATA_BUFFER, GenericReparseBuffer.DataBuffer) + pMSFTReparseBuffer->SymbolicLinkReparseBuffer.SubstituteNameLength; } else if ( bDriveLetter) { if( ulRemainingLen < (ULONG) FIELD_OFFSET( REPARSE_DATA_BUFFER, SymbolicLinkReparseBuffer.PathBuffer) + /* Display Name */ pCcb->DirectoryCB->NameInformation.TargetName.Length + /* Substitute Name */ pCcb->DirectoryCB->NameInformation.TargetName.Length + 4 * sizeof( WCHAR)) { ntStatus = STATUS_BUFFER_TOO_SMALL; Irp->IoStatus.Information = FIELD_OFFSET( REPARSE_DATA_BUFFER, SymbolicLinkReparseBuffer.PathBuffer) + pCcb->DirectoryCB->NameInformation.TargetName.Length + pCcb->DirectoryCB->NameInformation.TargetName.Length + 4 * sizeof( WCHAR); break; } pMSFTReparseBuffer->SymbolicLinkReparseBuffer.Flags = 0; pMSFTReparseBuffer->SymbolicLinkReparseBuffer.SubstituteNameLength = pCcb->DirectoryCB->NameInformation.TargetName.Length + 4 * sizeof( WCHAR); pMSFTReparseBuffer->SymbolicLinkReparseBuffer.PrintNameLength = pCcb->DirectoryCB->NameInformation.TargetName.Length; pMSFTReparseBuffer->SymbolicLinkReparseBuffer.SubstituteNameOffset = pMSFTReparseBuffer->SymbolicLinkReparseBuffer.PrintNameLength; pMSFTReparseBuffer->SymbolicLinkReparseBuffer.PrintNameOffset = 0; PathBuffer = pMSFTReparseBuffer->SymbolicLinkReparseBuffer.PathBuffer; /* Display Name */ RtlCopyMemory( PathBuffer, pCcb->DirectoryCB->NameInformation.TargetName.Buffer, pCcb->DirectoryCB->NameInformation.TargetName.Length); PathBuffer += pCcb->DirectoryCB->NameInformation.TargetName.Length / sizeof( WCHAR); /* Substitute Name */ *PathBuffer++ = L'\\'; *PathBuffer++ = L'?'; *PathBuffer++ = L'?'; *PathBuffer++ = L'\\'; RtlCopyMemory( PathBuffer, pCcb->DirectoryCB->NameInformation.TargetName.Buffer, pCcb->DirectoryCB->NameInformation.TargetName.Length); pReparseBuffer->ReparseDataLength = FIELD_OFFSET( REPARSE_DATA_BUFFER, SymbolicLinkReparseBuffer.PathBuffer) - FIELD_OFFSET( REPARSE_DATA_BUFFER, GenericReparseBuffer.DataBuffer) + pMSFTReparseBuffer->SymbolicLinkReparseBuffer.PrintNameLength + pMSFTReparseBuffer->SymbolicLinkReparseBuffer.SubstituteNameLength; } else { if( ulRemainingLen < (ULONG) FIELD_OFFSET( REPARSE_DATA_BUFFER, SymbolicLinkReparseBuffer.PathBuffer) + /* Display Name */ pCcb->DirectoryCB->NameInformation.TargetName.Length + 1 * sizeof( WCHAR) + /* Substitute Name */ pCcb->DirectoryCB->NameInformation.TargetName.Length + 7 * sizeof( WCHAR)) { ntStatus = STATUS_BUFFER_TOO_SMALL; Irp->IoStatus.Information = FIELD_OFFSET( REPARSE_DATA_BUFFER, SymbolicLinkReparseBuffer.PathBuffer) + pCcb->DirectoryCB->NameInformation.TargetName.Length + 1 * sizeof( WCHAR) + pCcb->DirectoryCB->NameInformation.TargetName.Length + 7 * sizeof( WCHAR); break; } pMSFTReparseBuffer->SymbolicLinkReparseBuffer.Flags = 0; pMSFTReparseBuffer->SymbolicLinkReparseBuffer.SubstituteNameLength = pCcb->DirectoryCB->NameInformation.TargetName.Length + 7 * sizeof( WCHAR); pMSFTReparseBuffer->SymbolicLinkReparseBuffer.PrintNameLength = pCcb->DirectoryCB->NameInformation.TargetName.Length + 1 * sizeof( WCHAR); pMSFTReparseBuffer->SymbolicLinkReparseBuffer.SubstituteNameOffset = pMSFTReparseBuffer->SymbolicLinkReparseBuffer.PrintNameLength; pMSFTReparseBuffer->SymbolicLinkReparseBuffer.PrintNameOffset = 0; PathBuffer = pMSFTReparseBuffer->SymbolicLinkReparseBuffer.PathBuffer; /* Display Name */ *PathBuffer++ = L'\\'; RtlCopyMemory( PathBuffer, pCcb->DirectoryCB->NameInformation.TargetName.Buffer, pCcb->DirectoryCB->NameInformation.TargetName.Length); PathBuffer += pCcb->DirectoryCB->NameInformation.TargetName.Length / sizeof( WCHAR); /* Substitute Name */ *PathBuffer++ = L'\\'; *PathBuffer++ = L'?'; *PathBuffer++ = L'?'; *PathBuffer++ = L'\\'; *PathBuffer++ = L'U'; *PathBuffer++ = L'N'; *PathBuffer++ = L'C'; RtlCopyMemory( PathBuffer, pCcb->DirectoryCB->NameInformation.TargetName.Buffer, pCcb->DirectoryCB->NameInformation.TargetName.Length); pReparseBuffer->ReparseDataLength = FIELD_OFFSET( REPARSE_DATA_BUFFER, SymbolicLinkReparseBuffer.PathBuffer) - FIELD_OFFSET( REPARSE_DATA_BUFFER, GenericReparseBuffer.DataBuffer) + pMSFTReparseBuffer->SymbolicLinkReparseBuffer.PrintNameLength + pMSFTReparseBuffer->SymbolicLinkReparseBuffer.SubstituteNameLength; } break; } default: ntStatus = STATUS_NOT_A_REPARSE_POINT; break; } if ( ntStatus == STATUS_SUCCESS) { ulRemainingLen -= pReparseBuffer->ReparseDataLength; if ( pFcb->ObjectInformation->FileType == AFS_FILE_TYPE_MOUNTPOINT) { pReparseBuffer->ReparseTag = IO_REPARSE_TAG_SURROGATE|IO_REPARSE_TAG_OPENAFS_DFS; RtlCopyMemory( &pReparseBuffer->ReparseGuid, &GUID_AFS_REPARSE_GUID, sizeof( GUID)); Irp->IoStatus.Information = FIELD_OFFSET( REPARSE_GUID_DATA_BUFFER, GenericReparseBuffer.DataBuffer) + pReparseBuffer->ReparseDataLength; } else { pReparseBuffer->ReparseTag = IO_REPARSE_TAG_SYMLINK; Irp->IoStatus.Information = FIELD_OFFSET( REPARSE_DATA_BUFFER, GenericReparseBuffer.DataBuffer) + pReparseBuffer->ReparseDataLength; } } AFSReleaseResource( &pCcb->DirectoryCB->NonPaged->Lock); break; } case FSCTL_SET_REPARSE_POINT: { REPARSE_GUID_DATA_BUFFER *pReparseGUIDBuffer = (REPARSE_GUID_DATA_BUFFER *)Irp->AssociatedIrp.SystemBuffer; REPARSE_DATA_BUFFER *pReparseBuffer = NULL; AFSReparseTagInfo *pReparseInfo = NULL; AFSObjectInfoCB *pParentObjectInfo = NULL; UNICODE_STRING uniTargetName; ULONGLONG ullIndex = 0; LONG lCount; AFSDbgTrace(( AFS_SUBSYSTEM_FILE_PROCESSING, AFS_TRACE_LEVEL_VERBOSE, "AFSProcessUserFsRequest Processing FSCTL_SET_REPARSE_POINT request %wZ Type 0x%x Attrib 0x%x\n", &pCcb->DirectoryCB->NameInformation.FileName, pFcb->ObjectInformation->FileType, pFcb->ObjectInformation->FileAttributes)); if( ulInputBufferLen < FIELD_OFFSET( REPARSE_GUID_DATA_BUFFER, GenericReparseBuffer.DataBuffer)) { ntStatus = STATUS_IO_REPARSE_DATA_INVALID; break; } if( (pReparseGUIDBuffer->ReparseTag & 0x0000FFFF) == IO_REPARSE_TAG_OPENAFS_DFS) { if( RtlCompareMemory( &pReparseGUIDBuffer->ReparseGuid, &GUID_AFS_REPARSE_GUID, sizeof( GUID)) != sizeof( GUID)) { ntStatus = STATUS_REPARSE_ATTRIBUTE_CONFLICT; break; } if( ulInputBufferLen < FIELD_OFFSET( REPARSE_GUID_DATA_BUFFER, GenericReparseBuffer.DataBuffer) + sizeof( AFSReparseTagInfo)) { ntStatus = STATUS_IO_REPARSE_DATA_INVALID; break; } pReparseInfo = (AFSReparseTagInfo *)pReparseGUIDBuffer->GenericReparseBuffer.DataBuffer; switch( pReparseInfo->SubTag) { case OPENAFS_SUBTAG_SYMLINK: { if( ulInputBufferLen < (ULONG)(FIELD_OFFSET( REPARSE_GUID_DATA_BUFFER, GenericReparseBuffer.DataBuffer) + FIELD_OFFSET( AFSReparseTagInfo, AFSSymLink.Buffer) + pReparseInfo->AFSSymLink.SymLinkTargetLength)) { ntStatus = STATUS_IO_REPARSE_DATA_INVALID; break; } uniTargetName.Length = pReparseInfo->AFSSymLink.SymLinkTargetLength; uniTargetName.MaximumLength = uniTargetName.Length; uniTargetName.Buffer = (WCHAR *)pReparseInfo->AFSSymLink.Buffer; break; } case OPENAFS_SUBTAG_UNC: { if( ulInputBufferLen < (ULONG)(FIELD_OFFSET( REPARSE_GUID_DATA_BUFFER, GenericReparseBuffer.DataBuffer) + FIELD_OFFSET( AFSReparseTagInfo, UNCReferral.Buffer) + pReparseInfo->UNCReferral.UNCTargetLength)) { ntStatus = STATUS_IO_REPARSE_DATA_INVALID; break; } uniTargetName.Length = pReparseInfo->UNCReferral.UNCTargetLength; uniTargetName.MaximumLength = uniTargetName.Length; uniTargetName.Buffer = (WCHAR *)pReparseInfo->UNCReferral.Buffer; break; } case OPENAFS_SUBTAG_MOUNTPOINT: // // Not yet handled // default: { ntStatus = STATUS_IO_REPARSE_DATA_INVALID; break; } } } else { // // Handle Microsoft Reparse Tags // switch( pReparseGUIDBuffer->ReparseTag) { case IO_REPARSE_TAG_MOUNT_POINT: { pReparseBuffer = (REPARSE_DATA_BUFFER *)Irp->AssociatedIrp.SystemBuffer; uniTargetName.Length = pReparseBuffer->MountPointReparseBuffer.PrintNameLength; uniTargetName.MaximumLength = uniTargetName.Length; uniTargetName.Buffer = (WCHAR *)((char *)pReparseBuffer->MountPointReparseBuffer.PathBuffer + pReparseBuffer->MountPointReparseBuffer.PrintNameOffset); AFSDbgTrace(( AFS_SUBSYSTEM_FILE_PROCESSING, AFS_TRACE_LEVEL_VERBOSE_2, "AFSProcessUserFsRequest IO_REPARSE_TAG_MOUNT_POINT request %wZ\n", &uniTargetName)); ntStatus = STATUS_IO_REPARSE_DATA_INVALID; break; } case IO_REPARSE_TAG_SYMLINK: { pReparseBuffer = (REPARSE_DATA_BUFFER *)Irp->AssociatedIrp.SystemBuffer; uniTargetName.Length = pReparseBuffer->SymbolicLinkReparseBuffer.SubstituteNameLength; uniTargetName.MaximumLength = uniTargetName.Length; uniTargetName.Buffer = (WCHAR *)((char *)pReparseBuffer->SymbolicLinkReparseBuffer.PathBuffer + pReparseBuffer->SymbolicLinkReparseBuffer.SubstituteNameOffset); AFSDbgTrace(( AFS_SUBSYSTEM_FILE_PROCESSING, AFS_TRACE_LEVEL_VERBOSE_2, "AFSProcessUserFsRequest IO_REPARSE_TAG_SYMLINK request %wZ\n", &uniTargetName)); break; } default: { ntStatus = STATUS_IO_REPARSE_DATA_INVALID; break; } } } if( !NT_SUCCESS( ntStatus)) { break; } // // First thing is to locate/create our object information block // for this entry // AFSAcquireExcl( pFcb->ObjectInformation->VolumeCB->ObjectInfoTree.TreeLock, TRUE); if ( AFSIsVolumeFID( &pFcb->ObjectInformation->ParentFileId)) { pParentObjectInfo = &pFcb->ObjectInformation->VolumeCB->ObjectInformation; } else { ullIndex = AFSCreateLowIndex( &pFcb->ObjectInformation->ParentFileId); ntStatus = AFSLocateHashEntry( pFcb->ObjectInformation->VolumeCB->ObjectInfoTree.TreeHead, ullIndex, (AFSBTreeEntry **)&pParentObjectInfo); } if ( NT_SUCCESS( ntStatus)) { lCount = AFSObjectInfoIncrement( pParentObjectInfo, AFS_OBJECT_REFERENCE_FS_REQ); AFSDbgTrace(( AFS_SUBSYSTEM_OBJECT_REF_COUNTING, AFS_TRACE_LEVEL_VERBOSE, "AFSProcessUserFsRequest Increment count on object %p Cnt %d\n", pParentObjectInfo, lCount)); KeQueryTickCount( &pParentObjectInfo->LastAccessCount); } AFSReleaseResource( pFcb->ObjectInformation->VolumeCB->ObjectInfoTree.TreeLock); if ( NT_SUCCESS( ntStatus)) { // // Extract out the information to the call to the service // ntStatus = AFSCreateSymlink( &pCcb->AuthGroup, pParentObjectInfo, &pCcb->DirectoryCB->NameInformation.FileName, pFcb->ObjectInformation, &uniTargetName); AFSDbgTrace(( AFS_SUBSYSTEM_FILE_PROCESSING, AFS_TRACE_LEVEL_VERBOSE_2, "AFSProcessUserFsRequest Processed FSCTL_SET_REPARSE_POINT request %wZ Type 0x%x Attrib 0x%x Status %08lX\n", &pCcb->DirectoryCB->NameInformation.FileName, pFcb->ObjectInformation->FileType, pFcb->ObjectInformation->FileAttributes, ntStatus)); AFSAcquireShared( pFcb->ObjectInformation->VolumeCB->ObjectInfoTree.TreeLock, TRUE); lCount = AFSObjectInfoDecrement( pParentObjectInfo, AFS_OBJECT_REFERENCE_FS_REQ); AFSDbgTrace(( AFS_SUBSYSTEM_OBJECT_REF_COUNTING, AFS_TRACE_LEVEL_VERBOSE, "AFSProcessUserFsRequest Decrement count on object %p Cnt %d\n", pParentObjectInfo, lCount)); AFSReleaseResource( pFcb->ObjectInformation->VolumeCB->ObjectInfoTree.TreeLock); } break; } case FSCTL_DELETE_REPARSE_POINT: { REPARSE_GUID_DATA_BUFFER *pReparseBuffer = (REPARSE_GUID_DATA_BUFFER *)Irp->AssociatedIrp.SystemBuffer; AFSDbgTrace(( AFS_SUBSYSTEM_FILE_PROCESSING, AFS_TRACE_LEVEL_VERBOSE_2, "AFSProcessUserFsRequest Processing FSCTL_DELETE_REPARSE_POINT request %wZ Type 0x%x Attrib 0x%x\n", &pCcb->DirectoryCB->NameInformation.FileName, pFcb->ObjectInformation->FileType, pFcb->ObjectInformation->FileAttributes)); // // Check if we have the reparse entry set on the entry // if( !BooleanFlagOn( pFcb->ObjectInformation->FileAttributes, FILE_ATTRIBUTE_REPARSE_POINT)) { ntStatus = STATUS_NOT_A_REPARSE_POINT; break; } if( ulInputBufferLen < FIELD_OFFSET( REPARSE_GUID_DATA_BUFFER, GenericReparseBuffer.DataBuffer)) { ntStatus = STATUS_INVALID_PARAMETER; break; } if( (pReparseBuffer->ReparseTag & 0x0000FFFF) != IO_REPARSE_TAG_OPENAFS_DFS) { ntStatus = STATUS_IO_REPARSE_TAG_MISMATCH; break; } if( RtlCompareMemory( &pReparseBuffer->ReparseGuid, &GUID_AFS_REPARSE_GUID, sizeof( GUID)) != sizeof( GUID)) { ntStatus = STATUS_REPARSE_ATTRIBUTE_CONFLICT; break; } // // Claim success. The typical usage is setting delete on close // as the next operation on the reparse point before closing // the handle. // ntStatus = STATUS_SUCCESS; break; } #ifndef FSCTL_SET_PURGE_FAILURE_MODE #define FSCTL_SET_PURGE_FAILURE_MODE CTL_CODE(FILE_DEVICE_FILE_SYSTEM, 156, METHOD_BUFFERED, FILE_ANY_ACCESS) #endif case FSCTL_SET_PURGE_FAILURE_MODE: { // // For the time being just succeed this call // ntStatus = STATUS_SUCCESS; break; } default : { AFSDbgTrace(( AFS_SUBSYSTEM_FILE_PROCESSING, AFS_TRACE_LEVEL_VERBOSE_2, "AFSProcessUserFsRequest Processing default (%08lX) request\n", ulFsControlCode)); ntStatus = STATUS_INVALID_DEVICE_REQUEST; break; } } try_exit: NOTHING; } return ntStatus; }
void AFSProcessCreate( IN HANDLE ParentId, IN HANDLE ProcessId, IN HANDLE CreatingProcessId, IN HANDLE CreatingThreadId) { AFSDeviceExt *pDeviceExt = (AFSDeviceExt *)AFSDeviceObject->DeviceExtension; AFSProcessCB *pProcessCB = NULL; __Enter { AFSDbgTrace(( AFS_SUBSYSTEM_LOCK_PROCESSING, AFS_TRACE_LEVEL_VERBOSE, "AFSProcessCreate Acquiring Control ProcessTree.TreeLock lock %p EXCL %08lX\n", pDeviceExt->Specific.Control.ProcessTree.TreeLock, PsGetCurrentThread())); AFSAcquireExcl( pDeviceExt->Specific.Control.ProcessTree.TreeLock, TRUE); AFSDbgTrace(( AFS_SUBSYSTEM_PROCESS_PROCESSING, AFS_TRACE_LEVEL_VERBOSE, "AFSProcessCreate Parent %08lX Process %08lX %08lX\n", ParentId, ProcessId, PsGetCurrentThread())); pProcessCB = AFSInitializeProcessCB( (ULONGLONG)ParentId, (ULONGLONG)ProcessId); if( pProcessCB != NULL) { pProcessCB->CreatingProcessId = (ULONGLONG)CreatingProcessId; pProcessCB->CreatingThreadId = (ULONGLONG)CreatingThreadId; // // Now assign the AuthGroup ACE // AFSValidateProcessEntry( ProcessId, TRUE); } else { AFSDbgTrace(( AFS_SUBSYSTEM_PROCESS_PROCESSING, AFS_TRACE_LEVEL_ERROR, "AFSProcessCreate Initialization failure for Parent %08lX Process %08lX %08lX\n", ParentId, ProcessId, PsGetCurrentThread())); } AFSReleaseResource( pDeviceExt->Specific.Control.ProcessTree.TreeLock); } return; }
GUID * AFSValidateProcessEntry( IN HANDLE ProcessId, IN BOOLEAN bProcessTreeLocked) { GUID *pAuthGroup = NULL; NTSTATUS ntStatus = STATUS_SUCCESS; AFSProcessCB *pProcessCB = NULL, *pParentProcessCB = NULL; AFSDeviceExt *pDeviceExt = (AFSDeviceExt *)AFSDeviceObject->DeviceExtension; ULONGLONG ullProcessID = (ULONGLONG)ProcessId; UNICODE_STRING uniSIDString; ULONG ulSIDHash = 0; AFSSIDEntryCB *pSIDEntryCB = NULL; ULONG ulSessionId = 0; ULONGLONG ullTableHash = 0; AFSThreadCB *pParentThreadCB = NULL; UNICODE_STRING uniGUID; BOOLEAN bImpersonation = FALSE; __Enter { uniSIDString.Length = 0; uniSIDString.MaximumLength = 0; uniSIDString.Buffer = NULL; if ( !bProcessTreeLocked) { AFSDbgTrace(( AFS_SUBSYSTEM_LOCK_PROCESSING, AFS_TRACE_LEVEL_VERBOSE, "AFSValidateProcessEntry Acquiring Control ProcessTree.TreeLock lock %p SHARED %08lX\n", pDeviceExt->Specific.Control.ProcessTree.TreeLock, PsGetCurrentThread())); AFSAcquireShared( pDeviceExt->Specific.Control.ProcessTree.TreeLock, TRUE); } AFSDbgTrace(( AFS_SUBSYSTEM_AUTHGROUP_PROCESSING, AFS_TRACE_LEVEL_VERBOSE, "%s Entry for ProcessID %I64X\n", __FUNCTION__, ullProcessID)); ntStatus = AFSLocateHashEntry( pDeviceExt->Specific.Control.ProcessTree.TreeHead, ullProcessID, (AFSBTreeEntry **)&pProcessCB); if( !NT_SUCCESS( ntStatus) || pProcessCB == NULL) { if ( !bProcessTreeLocked) { AFSReleaseResource( pDeviceExt->Specific.Control.ProcessTree.TreeLock); AFSAcquireExcl( pDeviceExt->Specific.Control.ProcessTree.TreeLock, TRUE); } ntStatus = AFSLocateHashEntry( pDeviceExt->Specific.Control.ProcessTree.TreeHead, ullProcessID, (AFSBTreeEntry **)&pProcessCB); if( !NT_SUCCESS( ntStatus) || pProcessCB == NULL) { AFSProcessCreate( 0, ProcessId, 0, 0); } if( !NT_SUCCESS( ntStatus) || pProcessCB == NULL) { AFSDbgTrace(( AFS_SUBSYSTEM_AUTHGROUP_PROCESSING, AFS_TRACE_LEVEL_ERROR, "%s Failed to locate process entry for ProcessID %I64X\n", __FUNCTION__, ullProcessID)); try_return( ntStatus = STATUS_UNSUCCESSFUL); } if ( !bProcessTreeLocked) { AFSConvertToShared( pDeviceExt->Specific.Control.ProcessTree.TreeLock); } } // // Locate and lock the ParentProcessCB if we have one // if( pProcessCB->ParentProcessId != 0) { AFSDbgTrace(( AFS_SUBSYSTEM_AUTHGROUP_PROCESSING, AFS_TRACE_LEVEL_VERBOSE, "%s Locating process entry for Parent ProcessID %I64X\n", __FUNCTION__, pProcessCB->ParentProcessId)); ntStatus = AFSLocateHashEntry( pDeviceExt->Specific.Control.ProcessTree.TreeHead, (ULONGLONG)pProcessCB->ParentProcessId, (AFSBTreeEntry **)&pParentProcessCB); if( NT_SUCCESS( ntStatus) && pParentProcessCB != NULL) { AFSAcquireExcl( &pParentProcessCB->Lock, TRUE); AFSDbgTrace(( AFS_SUBSYSTEM_AUTHGROUP_PROCESSING, AFS_TRACE_LEVEL_VERBOSE, "%s Located process entry for Parent ProcessID %I64X\n", __FUNCTION__, pProcessCB->ParentProcessId)); } } else { AFSDbgTrace(( AFS_SUBSYSTEM_AUTHGROUP_PROCESSING, AFS_TRACE_LEVEL_VERBOSE, "%s No parent ID for ProcessID %I64X\n", __FUNCTION__, ullProcessID)); } AFSAcquireExcl( &pProcessCB->Lock, TRUE); #if defined(_WIN64) // // Mark the process as 64-bit if it is. // if( !IoIs32bitProcess( NULL)) { SetFlag( pProcessCB->Flags, AFS_PROCESS_FLAG_IS_64BIT); } else { ClearFlag( pProcessCB->Flags, AFS_PROCESS_FLAG_IS_64BIT); } #endif // // Locate the SID for the caller // ntStatus = AFSGetCallerSID( &uniSIDString, &bImpersonation); if( !NT_SUCCESS( ntStatus)) { AFSDbgTrace(( AFS_SUBSYSTEM_AUTHGROUP_PROCESSING, AFS_TRACE_LEVEL_ERROR, "%s Failed to locate callers SID for ProcessID %I64X\n", __FUNCTION__, ullProcessID)); try_return( ntStatus); } ulSessionId = AFSGetSessionId( (HANDLE)ullProcessID, &bImpersonation); if( ulSessionId == (ULONG)-1) { AFSDbgTrace(( AFS_SUBSYSTEM_AUTHGROUP_PROCESSING, AFS_TRACE_LEVEL_ERROR, "%s Failed to retrieve session ID for ProcessID %I64X\n", __FUNCTION__, ullProcessID)); try_return( ntStatus = STATUS_INSUFFICIENT_RESOURCES); } AFSDbgTrace(( AFS_SUBSYSTEM_AUTHGROUP_PROCESSING, AFS_TRACE_LEVEL_VERBOSE, "%s Retrieved callers SID %wZ for ProcessID %I64X Session %08lX\n", __FUNCTION__, &uniSIDString, ullProcessID, ulSessionId)); // // If there is an Auth Group for the current process, // our job is finished. // if ( bImpersonation == FALSE) { pAuthGroup = pProcessCB->ActiveAuthGroup; if( pAuthGroup != NULL && !AFSIsNoPAGAuthGroup( pAuthGroup)) { uniGUID.Buffer = NULL; RtlStringFromGUID( *pAuthGroup, &uniGUID); AFSDbgTrace(( AFS_SUBSYSTEM_AUTHGROUP_PROCESSING, AFS_TRACE_LEVEL_VERBOSE, "%s Located valid AuthGroup GUID %wZ for SID %wZ ProcessID %I64X Session %08lX\n", __FUNCTION__, &uniGUID, &uniSIDString, ullProcessID, ulSessionId)); if( uniGUID.Buffer != NULL) { RtlFreeUnicodeString( &uniGUID); } try_return( ntStatus = STATUS_SUCCESS); } // // The current process does not yet have an Auth Group. Try to inherit // one from the parent process thread that created this process. // if( pParentProcessCB != NULL) { for ( pParentThreadCB = pParentProcessCB->ThreadList; pParentThreadCB != NULL; pParentThreadCB = pParentThreadCB->Next) { if( pParentThreadCB->ThreadId == pProcessCB->CreatingThreadId) { break; } } // // If the creating thread was found and it has a thread specific // Auth Group, use that even if it is the No PAG // if( pParentThreadCB != NULL && pParentThreadCB->ActiveAuthGroup != NULL && !AFSIsNoPAGAuthGroup( pParentThreadCB->ActiveAuthGroup)) { pProcessCB->ActiveAuthGroup = pParentThreadCB->ActiveAuthGroup; uniGUID.Buffer = NULL; RtlStringFromGUID( *(pProcessCB->ActiveAuthGroup), &uniGUID); AFSDbgTrace(( AFS_SUBSYSTEM_AUTHGROUP_PROCESSING, AFS_TRACE_LEVEL_VERBOSE, "%s PID %I64X Session %08lX inherited Active AuthGroup %wZ from thread %I64X\n", __FUNCTION__, ullProcessID, ulSessionId, &uniGUID, pParentThreadCB->ThreadId)); if( uniGUID.Buffer != NULL) { RtlFreeUnicodeString( &uniGUID); } } // // If the parent thread was not found or does not have an auth group // else if( pParentProcessCB->ActiveAuthGroup != NULL && !AFSIsNoPAGAuthGroup( pParentProcessCB->ActiveAuthGroup)) { pProcessCB->ActiveAuthGroup = pParentProcessCB->ActiveAuthGroup; uniGUID.Buffer = NULL; RtlStringFromGUID( *(pProcessCB->ActiveAuthGroup), &uniGUID); AFSDbgTrace(( AFS_SUBSYSTEM_AUTHGROUP_PROCESSING, AFS_TRACE_LEVEL_VERBOSE, "%s PID %I64X Session %08lX inherited Active AuthGroup %wZ from parent PID %I64X\n", __FUNCTION__, ullProcessID, ulSessionId, &uniGUID, pParentProcessCB->TreeEntry.HashIndex)); if( uniGUID.Buffer != NULL) { RtlFreeUnicodeString( &uniGUID); } } // // If an Auth Group was inherited, set it to be the active group // if( pProcessCB->ActiveAuthGroup != NULL && !AFSIsNoPAGAuthGroup( pParentProcessCB->ActiveAuthGroup)) { pAuthGroup = pProcessCB->ActiveAuthGroup; uniGUID.Buffer = NULL; RtlStringFromGUID( *(pProcessCB->ActiveAuthGroup), &uniGUID); AFSDbgTrace(( AFS_SUBSYSTEM_AUTHGROUP_PROCESSING, AFS_TRACE_LEVEL_VERBOSE, "%s Returning(1) Active AuthGroup %wZ for SID %wZ PID %I64X Session %08lX\n", __FUNCTION__, &uniGUID, &uniSIDString, ullProcessID, ulSessionId)); if( uniGUID.Buffer != NULL) { RtlFreeUnicodeString( &uniGUID); } try_return( ntStatus); } } } // // If no Auth Group was inherited, assign one based upon the Session and SID // ntStatus = RtlHashUnicodeString( &uniSIDString, TRUE, HASH_STRING_ALGORITHM_DEFAULT, &ulSIDHash); if( !NT_SUCCESS( ntStatus)) { AFSDbgTrace(( AFS_SUBSYSTEM_AUTHGROUP_PROCESSING, AFS_TRACE_LEVEL_ERROR, "%s Failed to hash SID %wZ for PID %I64X Session %08lX Status %08lX\n", __FUNCTION__, &uniSIDString, ullProcessID, ulSessionId, ntStatus)); try_return( ntStatus); } ullTableHash = ( ((ULONGLONG)ulSessionId << 32) | ulSIDHash); AFSAcquireShared( pDeviceExt->Specific.Control.AuthGroupTree.TreeLock, TRUE); ntStatus = AFSLocateHashEntry( pDeviceExt->Specific.Control.AuthGroupTree.TreeHead, (ULONGLONG)ullTableHash, (AFSBTreeEntry **)&pSIDEntryCB); if( !NT_SUCCESS( ntStatus) || pSIDEntryCB == NULL) { AFSReleaseResource( pDeviceExt->Specific.Control.AuthGroupTree.TreeLock); AFSAcquireExcl( pDeviceExt->Specific.Control.AuthGroupTree.TreeLock, TRUE); ntStatus = AFSLocateHashEntry( pDeviceExt->Specific.Control.AuthGroupTree.TreeHead, (ULONGLONG)ullTableHash, (AFSBTreeEntry **)&pSIDEntryCB); if( !NT_SUCCESS( ntStatus) || pSIDEntryCB == NULL) { pSIDEntryCB = (AFSSIDEntryCB *)AFSExAllocatePoolWithTag( NonPagedPool, sizeof( AFSSIDEntryCB), AFS_AG_ENTRY_CB_TAG); if( pSIDEntryCB == NULL) { AFSReleaseResource( pDeviceExt->Specific.Control.AuthGroupTree.TreeLock); try_return( ntStatus = STATUS_INSUFFICIENT_RESOURCES); } RtlZeroMemory( pSIDEntryCB, sizeof( AFSSIDEntryCB)); pSIDEntryCB->TreeEntry.HashIndex = (ULONGLONG)ullTableHash; while( ExUuidCreate( &pSIDEntryCB->AuthGroup) == STATUS_RETRY); uniGUID.Buffer = NULL; RtlStringFromGUID( pSIDEntryCB->AuthGroup, &uniGUID); AFSDbgTrace(( AFS_SUBSYSTEM_AUTHGROUP_PROCESSING, AFS_TRACE_LEVEL_VERBOSE, "%s SID %wZ PID %I64X Session %08lX generated NEW AG %wZ\n", __FUNCTION__, &uniSIDString, ullProcessID, ulSessionId, &uniGUID)); if( uniGUID.Buffer != NULL) { RtlFreeUnicodeString( &uniGUID); } if( pDeviceExt->Specific.Control.AuthGroupTree.TreeHead == NULL) { pDeviceExt->Specific.Control.AuthGroupTree.TreeHead = (AFSBTreeEntry *)pSIDEntryCB; } else { AFSInsertHashEntry( pDeviceExt->Specific.Control.AuthGroupTree.TreeHead, &pSIDEntryCB->TreeEntry); } } AFSConvertToShared( pDeviceExt->Specific.Control.AuthGroupTree.TreeLock); } AFSReleaseResource( pDeviceExt->Specific.Control.AuthGroupTree.TreeLock); // // Store the auth group into the process cb // pProcessCB->ActiveAuthGroup = &pSIDEntryCB->AuthGroup; uniGUID.Buffer = NULL; RtlStringFromGUID( pSIDEntryCB->AuthGroup, &uniGUID); AFSDbgTrace(( AFS_SUBSYSTEM_AUTHGROUP_PROCESSING, AFS_TRACE_LEVEL_VERBOSE, "%s SID %wZ PID %I64X Session %08lX assigned AG %wZ\n", __FUNCTION__, &uniSIDString, ullProcessID, ulSessionId, &uniGUID)); if( uniGUID.Buffer != NULL) { RtlFreeUnicodeString( &uniGUID); } // // Set the AFS_PROCESS_LOCAL_SYSTEM_AUTH flag if the process SID // is LOCAL_SYSTEM // if( AFSIsLocalSystemSID( &uniSIDString)) { SetFlag( pProcessCB->Flags, AFS_PROCESS_LOCAL_SYSTEM_AUTH); AFSDbgTrace(( AFS_SUBSYSTEM_AUTHGROUP_PROCESSING, AFS_TRACE_LEVEL_VERBOSE, "%s Setting PID %I64X Session %08lX with LOCAL SYSTEM AUTHORITY\n", __FUNCTION__, ullProcessID, ulSessionId)); } // // Return the auth group // pAuthGroup = pProcessCB->ActiveAuthGroup; uniGUID.Buffer = NULL; RtlStringFromGUID( *(pProcessCB->ActiveAuthGroup), &uniGUID); AFSDbgTrace(( AFS_SUBSYSTEM_AUTHGROUP_PROCESSING, AFS_TRACE_LEVEL_VERBOSE, "%s Returning(2) Active AuthGroup %wZ for SID %wZ PID %I64X Session %08lX\n", __FUNCTION__, &uniGUID, &uniSIDString, ullProcessID, ulSessionId)); if( uniGUID.Buffer != NULL) { RtlFreeUnicodeString( &uniGUID); } try_exit: if( pProcessCB != NULL) { if( bImpersonation == FALSE && !BooleanFlagOn( pProcessCB->Flags, AFS_PROCESS_FLAG_ACE_SET) && NT_SUCCESS( ntStatus)) { ntStatus = AFSProcessSetProcessDacl( pProcessCB); if( !NT_SUCCESS( ntStatus)) { pAuthGroup = NULL; } else { SetFlag( pProcessCB->Flags, AFS_PROCESS_FLAG_ACE_SET); } } AFSReleaseResource( &pProcessCB->Lock); } if( pParentProcessCB != NULL) { AFSReleaseResource( &pParentProcessCB->Lock); } if( uniSIDString.Length > 0) { RtlFreeUnicodeString( &uniSIDString); } if ( !bProcessTreeLocked) { AFSReleaseResource( pDeviceExt->Specific.Control.ProcessTree.TreeLock); } } return pAuthGroup; }
void AFSProcessDestroy( IN HANDLE ProcessId) { NTSTATUS ntStatus = STATUS_SUCCESS; AFSDeviceExt *pDeviceExt = (AFSDeviceExt *)AFSDeviceObject->DeviceExtension; AFSProcessCB *pProcessCB = NULL; AFSProcessAuthGroupCB *pProcessAuthGroup = NULL, *pLastAuthGroup = NULL; AFSThreadCB *pThreadCB = NULL, *pNextThreadCB = NULL; __Enter { AFSDbgTrace(( AFS_SUBSYSTEM_LOCK_PROCESSING, AFS_TRACE_LEVEL_VERBOSE, "AFSProcessDestroy Acquiring Control ProcessTree.TreeLock lock %p EXCL %08lX\n", pDeviceExt->Specific.Control.ProcessTree.TreeLock, PsGetCurrentThreadId())); AFSAcquireExcl( pDeviceExt->Specific.Control.ProcessTree.TreeLock, TRUE); // // It's a remove so pull the entry // AFSDbgTrace(( AFS_SUBSYSTEM_PROCESS_PROCESSING, AFS_TRACE_LEVEL_VERBOSE, "AFSProcessDestroy Process %08lX %08lX\n", ProcessId, PsGetCurrentThread())); ntStatus = AFSLocateHashEntry( pDeviceExt->Specific.Control.ProcessTree.TreeHead, (ULONGLONG)ProcessId, (AFSBTreeEntry **)&pProcessCB); if( NT_SUCCESS( ntStatus) && pProcessCB != NULL) { AFSRemoveHashEntry( &pDeviceExt->Specific.Control.ProcessTree.TreeHead, (AFSBTreeEntry *)pProcessCB); pProcessAuthGroup = pProcessCB->AuthGroupList; while( pProcessAuthGroup != NULL) { pLastAuthGroup = pProcessAuthGroup->Next; ExFreePool( pProcessAuthGroup); pProcessAuthGroup = pLastAuthGroup; } pThreadCB = pProcessCB->ThreadList; while( pThreadCB != NULL) { pNextThreadCB = pThreadCB->Next; ExFreePool( pThreadCB); pThreadCB = pNextThreadCB; } ExDeleteResourceLite( &pProcessCB->Lock); ExFreePool( pProcessCB); } else { AFSDbgTrace(( AFS_SUBSYSTEM_PROCESS_PROCESSING, AFS_TRACE_LEVEL_WARNING, "AFSProcessDestroy Process %08lX not found in ProcessTree Status %08lX %08lX\n", ProcessId, ntStatus, PsGetCurrentThread())); } AFSReleaseResource( pDeviceExt->Specific.Control.ProcessTree.TreeLock); } return; }
NTSTATUS AFSProcessQueuedResults( IN BOOLEAN CancelRequest) { NTSTATUS ntStatus = STATUS_SUCCESS; AFSLibraryQueueRequestCB *pRequest = NULL; AFSDeviceExt *pDevExt = (AFSDeviceExt *)AFSDeviceObject->DeviceExtension; __Enter { AFSDbgTrace(( AFS_SUBSYSTEM_LOAD_LIBRARY, AFS_TRACE_LEVEL_VERBOSE, "%s Entry\n", __FUNCTION__)); // // Loop through the queue either resubmitting requests or cancelling them // while( TRUE) { AFSAcquireExcl( &pDevExt->Specific.Control.LibraryQueueLock, TRUE); if( pDevExt->Specific.Control.LibraryQueueHead == NULL) { AFSReleaseResource( &pDevExt->Specific.Control.LibraryQueueLock); break; } pRequest = pDevExt->Specific.Control.LibraryQueueHead; pDevExt->Specific.Control.LibraryQueueHead = pRequest->fLink; if( pDevExt->Specific.Control.LibraryQueueHead == NULL) { pDevExt->Specific.Control.LibraryQueueTail = NULL; } AFSReleaseResource( &pDevExt->Specific.Control.LibraryQueueLock); if( CancelRequest) { pRequest->Irp->IoStatus.Status = STATUS_CANCELLED; AFSDbgTrace(( AFS_SUBSYSTEM_LOAD_LIBRARY, AFS_TRACE_LEVEL_VERBOSE, "%s Cancelling request Irp %p\n", __FUNCTION__, pRequest->Irp)); IoCompleteRequest( pRequest->Irp, IO_NO_INCREMENT); } else { AFSDbgTrace(( AFS_SUBSYSTEM_LOAD_LIBRARY, AFS_TRACE_LEVEL_VERBOSE, "%s Resubmitting request Irp %p\n", __FUNCTION__, pRequest->Irp)); AFSSubmitLibraryRequest( pRequest->Irp); } ExFreePool( pRequest); } AFSDbgTrace(( AFS_SUBSYSTEM_LOAD_LIBRARY, AFS_TRACE_LEVEL_VERBOSE, "%s Completed\n", __FUNCTION__)); } return ntStatus; }
NTSTATUS AFSQueueLibraryRequest( IN PIRP Irp) { NTSTATUS ntStatus = STATUS_SUCCESS; AFSDeviceExt *pDevExt = (AFSDeviceExt *)AFSDeviceObject->DeviceExtension; AFSDeviceExt *pRDRDevExt = (AFSDeviceExt *)AFSRDRDeviceObject->DeviceExtension; AFSLibraryQueueRequestCB *pRequest = NULL; PIO_STACK_LOCATION pIrpSp = IoGetCurrentIrpStackLocation( Irp); __Enter { AFSAcquireExcl( &pDevExt->Specific.Control.LibraryQueueLock, TRUE); AFSDbgTrace(( AFS_SUBSYSTEM_LOAD_LIBRARY, AFS_TRACE_LEVEL_VERBOSE, "%s Entry for Irp %p Function %08lX\n", __FUNCTION__, Irp, pIrpSp->MajorFunction)); // // Has the load processing timed out and we are no longer // queuing requests? // if( BooleanFlagOn( pDevExt->Specific.Control.LibraryState, AFS_LIBRARY_QUEUE_CANCELLED) || BooleanFlagOn( pRDRDevExt->DeviceFlags, AFS_DEVICE_FLAG_REDIRECTOR_SHUTDOWN)) { AFSDbgTrace(( AFS_SUBSYSTEM_LOAD_LIBRARY, AFS_TRACE_LEVEL_ERROR, "%s Library not loaded for Irp %p\n", __FUNCTION__, Irp)); try_return( ntStatus = STATUS_DEVICE_NOT_READY); } pRequest = (AFSLibraryQueueRequestCB *)AFSExAllocatePoolWithTag( PagedPool, sizeof( AFSLibraryQueueRequestCB), AFS_LIBRARY_QUEUE_TAG); if( pRequest == NULL) { try_return( ntStatus = STATUS_INSUFFICIENT_RESOURCES); } RtlZeroMemory( pRequest, sizeof( AFSLibraryQueueRequestCB)); pRequest->Irp = Irp; if( pDevExt->Specific.Control.LibraryQueueHead == NULL) { pDevExt->Specific.Control.LibraryQueueHead = pRequest; } else { pDevExt->Specific.Control.LibraryQueueTail->fLink = pRequest; } pDevExt->Specific.Control.LibraryQueueTail = pRequest; IoMarkIrpPending( Irp); ntStatus = STATUS_PENDING; try_exit: AFSDbgTrace(( AFS_SUBSYSTEM_LOAD_LIBRARY, AFS_TRACE_LEVEL_VERBOSE, "%s Completed for Irp %p Status %08lX\n", __FUNCTION__, Irp, ntStatus)); AFSReleaseResource( &pDevExt->Specific.Control.LibraryQueueLock); } 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 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 AFSDbgLogMsg( IN ULONG Subsystem, IN ULONG Level, IN PCCH Format, ...) { NTSTATUS ntStatus = STATUS_SUCCESS; va_list va_args; ULONG ulBytesWritten = 0; BOOLEAN bReleaseLock = FALSE; char *pCurrentTrace = NULL; __Enter { if( AFSDbgBuffer == NULL) { try_return( ntStatus = STATUS_DEVICE_NOT_READY); } if( Subsystem > 0 && (Subsystem & AFSTraceComponent) == 0) { // // Not tracing this subsystem // try_return( ntStatus); } if( Level > 0 && Level > AFSTraceLevel) { // // Not tracing this level // try_return( ntStatus); } AFSAcquireExcl( &AFSDbgLogLock, TRUE); bReleaseLock = TRUE; // // Check again under lock // if( AFSDbgBuffer == NULL) { try_return( ntStatus = STATUS_DEVICE_NOT_READY); } if( AFSDbgLogRemainingLength < 255) { AFSDbgLogRemainingLength = AFSDbgBufferLength; AFSDbgCurrentBuffer = AFSDbgBuffer; SetFlag( AFSDbgLogFlags, AFS_DBG_LOG_WRAPPED); } pCurrentTrace = AFSDbgCurrentBuffer; RtlStringCchPrintfA( AFSDbgCurrentBuffer, 10, "%08lX:", AFSDbgLogCounter++); AFSDbgCurrentBuffer += 9; AFSDbgLogRemainingLength -= 9; va_start( va_args, Format); ntStatus = RtlStringCbVPrintfA( AFSDbgCurrentBuffer, AFSDbgLogRemainingLength, Format, va_args); if( ntStatus == STATUS_BUFFER_OVERFLOW) { RtlZeroMemory( AFSDbgCurrentBuffer, AFSDbgLogRemainingLength); AFSDbgLogRemainingLength = AFSDbgBufferLength; AFSDbgCurrentBuffer = AFSDbgBuffer; SetFlag( AFSDbgLogFlags, AFS_DBG_LOG_WRAPPED); pCurrentTrace = AFSDbgCurrentBuffer; RtlStringCchPrintfA( AFSDbgCurrentBuffer, 10, "%08lX:", AFSDbgLogCounter++); AFSDbgCurrentBuffer += 9; AFSDbgLogRemainingLength -= 9; ntStatus = RtlStringCbVPrintfA( AFSDbgCurrentBuffer, AFSDbgLogRemainingLength, Format, va_args); } if( NT_SUCCESS( ntStatus)) { RtlStringCbLengthA( AFSDbgCurrentBuffer, AFSDbgLogRemainingLength, (size_t *)&ulBytesWritten); AFSDbgCurrentBuffer += ulBytesWritten; AFSDbgLogRemainingLength -= ulBytesWritten; } va_end( va_args); if( BooleanFlagOn( AFSDebugFlags, AFS_DBG_TRACE_TO_DEBUGGER) && pCurrentTrace != NULL) { DbgPrint( pCurrentTrace); } try_exit: if( bReleaseLock) { AFSReleaseResource( &AFSDbgLogLock); } } 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; }
NTSTATUS AFSRemoveCcb( IN AFSFcb *Fcb, IN AFSCcb *Ccb) { NTSTATUS ntStatus = STATUS_SUCCESS; if( Fcb != NULL && BooleanFlagOn( Ccb->Flags, CCB_FLAG_INSERTED_CCB_LIST)) { AFSAcquireExcl( &Fcb->NPFcb->CcbListLock, TRUE); if( Ccb->ListEntry.fLink == NULL) { Fcb->CcbListTail = (AFSCcb *)Ccb->ListEntry.bLink; if( Fcb->CcbListTail != NULL) { Fcb->CcbListTail->ListEntry.fLink = NULL; } } else { ((AFSCcb *)(Ccb->ListEntry.fLink))->ListEntry.bLink = Ccb->ListEntry.bLink; } if( Ccb->ListEntry.bLink == NULL) { Fcb->CcbListHead = (AFSCcb *)Ccb->ListEntry.fLink; if( Fcb->CcbListHead != NULL) { Fcb->CcbListHead->ListEntry.bLink = NULL; } } else { ((AFSCcb *)(Ccb->ListEntry.bLink))->ListEntry.fLink = Ccb->ListEntry.fLink; } AFSReleaseResource( &Fcb->NPFcb->CcbListLock); } if( Ccb->MaskName.Buffer != NULL) { AFSExFreePool( Ccb->MaskName.Buffer); } if( BooleanFlagOn( Ccb->Flags, CCB_FLAG_FREE_FULL_PATHNAME)) { AFSExFreePool( Ccb->FullFileName.Buffer); } // // If we have a name array then delete it // if( Ccb->NameArray != NULL) { AFSFreeNameArray( Ccb->NameArray); Ccb->NameArray = NULL; } if( Ccb->DirectorySnapshot != NULL) { AFSExFreePool( Ccb->DirectorySnapshot); Ccb->DirectorySnapshot = NULL; } if( Ccb->NotifyMask.Buffer != NULL) { AFSExFreePool( Ccb->NotifyMask.Buffer); } // // Free up the Ccb // AFSExFreePool( Ccb); return 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 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 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 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 AFSUnloadLibrary( IN BOOLEAN CancelQueue) { NTSTATUS ntStatus = STATUS_SUCCESS; AFSDeviceExt *pDevExt = (AFSDeviceExt *)AFSDeviceObject->DeviceExtension; LARGE_INTEGER liTimeout; __Enter { // // Wait on the load library event so we don't race with any // other requests coming through // AFSDbgTrace(( AFS_SUBSYSTEM_LOAD_LIBRARY, AFS_TRACE_LEVEL_VERBOSE, "%s Start unload library\n", __FUNCTION__)); ntStatus = KeWaitForSingleObject( &pDevExt->Specific.Control.LoadLibraryEvent, Executive, KernelMode, FALSE, NULL); if( !NT_SUCCESS( ntStatus)) { try_return( ntStatus); } if( !BooleanFlagOn( pDevExt->Specific.Control.LibraryState, AFS_LIBRARY_LOADED)) { try_return( ntStatus = STATUS_DEVICE_NOT_READY); } // // Clear all outstanding requests // AFSAcquireExcl( &pDevExt->Specific.Control.LibraryStateLock, TRUE); ClearFlag( pDevExt->Specific.Control.LibraryState, AFS_LIBRARY_LOADED); if( CancelQueue) { SetFlag( pDevExt->Specific.Control.LibraryState, AFS_LIBRARY_QUEUE_CANCELLED); } // // We'll wait on the inflight event to be set, checking for the inflight // request count to reach zero // while( pDevExt->Specific.Control.InflightLibraryRequests > 0) { liTimeout.QuadPart = -(AFS_ONE_SECOND); // // If the count is non-zero make sure the event is cleared // KeClearEvent( &pDevExt->Specific.Control.InflightLibraryEvent); AFSReleaseResource( &pDevExt->Specific.Control.LibraryStateLock); ntStatus = KeWaitForSingleObject( &pDevExt->Specific.Control.InflightLibraryEvent, Executive, KernelMode, FALSE, &liTimeout); AFSAcquireExcl( &pDevExt->Specific.Control.LibraryStateLock, TRUE); if( ntStatus != STATUS_TIMEOUT && ntStatus != STATUS_SUCCESS) { AFSDbgTrace(( AFS_SUBSYSTEM_LOAD_LIBRARY, AFS_TRACE_LEVEL_VERBOSE, "%s Failed request event Status %08lX\n", __FUNCTION__, ntStatus)); SetFlag( pDevExt->Specific.Control.LibraryState, AFS_LIBRARY_LOADED); AFSReleaseResource( &pDevExt->Specific.Control.LibraryStateLock); AFSProcessQueuedResults( TRUE); try_return( ntStatus); } AFSDbgTrace(( AFS_SUBSYSTEM_LOAD_LIBRARY, AFS_TRACE_LEVEL_VERBOSE, "%s Wait for inflight requests to complete %08lX\n", __FUNCTION__, pDevExt->Specific.Control.InflightLibraryRequests)); } AFSReleaseResource( &pDevExt->Specific.Control.LibraryStateLock); AFSDbgTrace(( AFS_SUBSYSTEM_LOAD_LIBRARY, AFS_TRACE_LEVEL_VERBOSE, "%s Processing queued results\n", __FUNCTION__)); AFSProcessQueuedResults( TRUE); // // Unload the current library implementation // if( pDevExt->Specific.Control.LibraryFileObject != NULL) { ObDereferenceObject( pDevExt->Specific.Control.LibraryFileObject); } pDevExt->Specific.Control.LibraryFileObject = NULL; pDevExt->Specific.Control.LibraryDeviceObject = NULL; ZwUnloadDriver( &pDevExt->Specific.Control.LibraryServicePath); ExFreePool( pDevExt->Specific.Control.LibraryServicePath.Buffer); pDevExt->Specific.Control.LibraryServicePath.Length = 0; pDevExt->Specific.Control.LibraryServicePath.MaximumLength = 0; pDevExt->Specific.Control.LibraryServicePath.Buffer = NULL; try_exit: AFSDbgTrace(( AFS_SUBSYSTEM_LOAD_LIBRARY, AFS_TRACE_LEVEL_VERBOSE, "%s Library unload complete Status %08lX\n", __FUNCTION__, ntStatus)); KeSetEvent( &pDevExt->Specific.Control.LoadLibraryEvent, 0, FALSE); } return ntStatus; }