CmRmFinalizeRecovery

NTSTATUS __stdcall CmRmFinalizeRecovery(CM_RM *CmRm){
  _ETHREAD *CurrentThread; 
  _LIST_ENTRY *p_TransactionListHead; 
  _CM_TRANS *Flink; 
  _LIST_ENTRY *v6; 
  _ADAPTER_OBJECT *KtmEnlistmentObject; 
  void *KtmEnlistmentHandle; 
  _ETHREAD *v9; 
  UINT64 UowCount; 
  _KAPC_STATE ApcState; 

  LODWORD(UowCount) = 0;
  memset(&ApcState, 0, sizeof(ApcState));
  CurrentThread = (_ETHREAD *)KeGetCurrentThread();
  --CurrentThread->Tcb.KernelApcDisable;
  ExAcquireFastMutexUnsafe((PFAST_MUTEX)((char *)&CmpDummyThreadEvent + 64));
  p_TransactionListHead = &CmRm->TransactionListHead;
  while( 1 )
  {
    Flink = (_CM_TRANS *)p_TransactionListHead->Flink;
    if( p_TransactionListHead->Flink == p_TransactionListHead )
      break;
    if( Flink->TransactionListEntry.Blink != p_TransactionListHead
      || (v6 = Flink->TransactionListEntry.Flink, (_CM_TRANS *)Flink->TransactionListEntry.Flink->Blink != Flink) )
    {
      __fastfail(3u);
    }
    p_TransactionListHead->Flink = v6;
    v6->Blink = p_TransactionListHead;
    ExReleaseFastMutexUnsafe((PFAST_MUTEX)((char *)&CmpDummyThreadEvent + 64));
    KeLeaveCriticalRegionThread(KeGetCurrentThread());
    CmpTransMgrRollback(Flink, &UowCount);
    CmpAttachToRegistryProcess(&ApcState);
    CmpTransMgrFreeVolatileData(Flink, 8ui64);
    KiUnstackDetachProcess(&ApcState, 0i64);
    if( Flink->Trans.0 )
      CmpTransDereferenceTransaction((INT64)Flink->Trans.TransPtr);
    KtmEnlistmentObject = (_ADAPTER_OBJECT *)Flink->KtmEnlistmentObject;
    if( KtmEnlistmentObject )
      HalPutDmaAdapter(KtmEnlistmentObject);
    KtmEnlistmentHandle = Flink->KtmEnlistmentHandle;
    if( KtmEnlistmentHandle )
      ZwClose((_HANDLE)KtmEnlistmentHandle);
    ExFreePoolWithTag(Flink, 0x72544D43u);
    v9 = (_ETHREAD *)KeGetCurrentThread();
    --v9->Tcb.KernelApcDisable;
    ExAcquireFastMutexUnsafe((PFAST_MUTEX)((char *)&CmpDummyThreadEvent + 64));
  }
  ExReleaseFastMutexUnsafe((PFAST_MUTEX)((char *)&CmpDummyThreadEvent + 64));
  KeLeaveCriticalRegionThread(KeGetCurrentThread());
  return 0;
}

Referenced by:

CmpFinishSystemHivesLoad
CmpLoadKeyCommon
CmpMountPreloadedHives