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 AFSRemoveVolume( IN AFSVolumeCB *VolumeCB) { NTSTATUS ntStatus = STATUS_SUCCESS; AFSDeviceExt *pDeviceExt = (AFSDeviceExt *)AFSRDRDeviceObject->DeviceExtension; __Enter { // // Remove the volume from the tree and list // Don't process the list information for reserved entries // if( VolumeCB->ObjectInformation.FileId.Cell != 0) { if( BooleanFlagOn( VolumeCB->Flags, AFS_VOLUME_INSERTED_HASH_TREE)) { AFSRemoveHashEntry( &pDeviceExt->Specific.RDR.VolumeTree.TreeHead, &VolumeCB->TreeEntry); } if( VolumeCB->ListEntry.fLink == NULL) { pDeviceExt->Specific.RDR.VolumeListTail = (AFSVolumeCB *)VolumeCB->ListEntry.bLink; if( pDeviceExt->Specific.RDR.VolumeListTail != NULL) { pDeviceExt->Specific.RDR.VolumeListTail->ListEntry.fLink = NULL; } } else { ((AFSVolumeCB *)(VolumeCB->ListEntry.fLink))->ListEntry.bLink = VolumeCB->ListEntry.bLink; } if( VolumeCB->ListEntry.bLink == NULL) { pDeviceExt->Specific.RDR.VolumeListHead = (AFSVolumeCB *)VolumeCB->ListEntry.fLink; if( pDeviceExt->Specific.RDR.VolumeListHead != NULL) { pDeviceExt->Specific.RDR.VolumeListHead->ListEntry.bLink = NULL; } } else { ((AFSVolumeCB *)(VolumeCB->ListEntry.bLink))->ListEntry.fLink = VolumeCB->ListEntry.fLink; } } // // Remove any PIOctl objects we have // if( VolumeCB->ObjectInformation.Specific.Directory.PIOCtlDirectoryCB != NULL) { if( VolumeCB->ObjectInformation.Specific.Directory.PIOCtlDirectoryCB->ObjectInformation->Fcb != NULL) { AFSRemoveFcb( VolumeCB->ObjectInformation.Specific.Directory.PIOCtlDirectoryCB->ObjectInformation->Fcb); } AFSDeleteObjectInfo( VolumeCB->ObjectInformation.Specific.Directory.PIOCtlDirectoryCB->ObjectInformation); AFSExFreePool( VolumeCB->ObjectInformation.Specific.Directory.PIOCtlDirectoryCB); } if( BooleanFlagOn( VolumeCB->ObjectInformation.Flags, AFS_OBJECT_HELD_IN_SERVICE)) { // // Release the fid in the service // AFSReleaseFid( &VolumeCB->ObjectInformation.FileId); } // // Free up the memory // if( VolumeCB->NonPagedVcb != NULL) { if( ExIsResourceAcquiredLite( VolumeCB->VolumeLock)) { AFSReleaseResource( VolumeCB->VolumeLock); } ExDeleteResourceLite( &VolumeCB->NonPagedVcb->VolumeLock); ExDeleteResourceLite( &VolumeCB->NonPagedVcb->ObjectInfoTreeLock); AFSExFreePool( VolumeCB->NonPagedVcb); } if( VolumeCB->ObjectInformation.NonPagedInfo != NULL) { ExDeleteResourceLite( &VolumeCB->ObjectInformation.NonPagedInfo->DirectoryNodeHdrLock); AFSExFreePool( VolumeCB->ObjectInformation.NonPagedInfo); } if( VolumeCB->DirectoryCB != NULL) { if( VolumeCB->DirectoryCB->NonPaged != NULL) { ExDeleteResourceLite( &VolumeCB->DirectoryCB->NonPaged->Lock); AFSExFreePool( VolumeCB->DirectoryCB->NonPaged); } AFSExFreePool( VolumeCB->DirectoryCB); } AFSExFreePool( VolumeCB); } return ntStatus; }
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; }