VrpUnloadDifferencingHive

NTSTATUS __stdcall VrpUnloadDifferencingHive(UNICODE_STRING *TargetKeyPath){
  _ETHREAD *CurrentThread; 
  __int64 v3; 
  __int64 v4; 
  _ETHREAD *v5; 
  volatile signed __int64 *v6; 
  char v7; 
  char v8; 
  char v9; 
  int v10; 
  _ETHREAD *v11; 
  char v12; 
  signed __int64 v14; 
  unsigned __int64 i; 
  signed __int64 v16; 
  struct _OBJECT_ATTRIBUTES KeyObjectAttributes; 
  memset(&KeyObjectAttributes, 0, sizeof(KeyObjectAttributes));
  CurrentThread = (_ETHREAD *)KeGetCurrentThread();
  --*((_WORD *)CurrentThread + 242);
  ExAcquirePushLockSharedEx((UINT64)&gLoadedDiffHivesLock, 0i64);
  LODWORD(v3) = VrpFindDiffHiveEntryForMountPointWithLock(TargetKeyPath);
  v4 = v3;
  if( v3 && _InterlockedIncrement64((volatile signed __int64 *)(v3 + 16)) <= 1 )
    __fastfail(0xEu);
  ExReleasePushLockEx((UINT64)&gLoadedDiffHivesLock, 0i64);
  KeLeaveCriticalRegionThread((__int64)KeGetCurrentThread());
  if( !v4 )
    return -1073741772;
  v5 = (_ETHREAD *)KeGetCurrentThread();
  --*((_WORD *)v5 + 242);
  v6 = (volatile signed __int64 *)(v4 + 24);
  ExAcquirePushLockExclusiveEx(v4 + 24, 0i64);
  if( VrpDecrementDiffHiveEntryHardRefCount(v4) )
  {
    v7 = VrpBecomeDiffHiveEntryTransitionOwner(v4);
    *(_DWORD *)(v4 + 56) &= ~1u;
    v8 = v7;
    v9 = _InterlockedExchangeAdd64(v6, 0xFFFFFFFFFFFFFFFFui64);
    if( (v9 & 2) != 0 && (v9 & 4) == 0 )
      ExfTryToWakePushLock((volatile INT64 *)(v4 + 24));
    KeAbPostRelease((PVOID)(v4 + 24));
    KeLeaveCriticalRegionThread((__int64)KeGetCurrentThread());
    KeyObjectAttributes.RootDirectory = 0i64;
    KeyObjectAttributes.Length = 48;
    *(_OWORD *)&KeyObjectAttributes.SecurityDescriptor = 0i64;
    KeyObjectAttributes.Attributes = 576;
    KeyObjectAttributes.ObjectName = TargetKeyPath;
    v10 = ZwUnloadKey(&KeyObjectAttributes);
    if( v10 < 0 )
      v10 = ZwUnloadKey2(&KeyObjectAttributes, 1ui64);
    v11 = (_ETHREAD *)KeGetCurrentThread();
    --*((_WORD *)v11 + 242);
    ExAcquirePushLockExclusiveEx(v4 + 24, 0i64);
    if( v10 < 0 )
    {
      *(_DWORD *)(v4 + 56) |= 1u;
      if( ++*(_QWORD *)(v4 + 32) <= 1ui64 )
      {
        _m_prefetchw((const void *)(v4 + 16));
        v14 = *(_QWORD *)(v4 + 16);
        for( i = v14 + 1; ; i = v14 + 1 )
        {
          if( i <= 1 )
          {
            if( i != 1 )
              __fastfail(0xEu);
            __fastfail(0xEu);
          }
          v16 = v14;
          v14 = _InterlockedCompareExchange64((volatile signed __int64 *)(v4 + 16), i, v14);
          if( v16 == v14 )
            break;
        }
      }
    }
    if( v8 )
      VrpRelinquishDiffHiveEntryTransitionOwner(v4);
  }
  else
  {
    v10 = 0;
  }
  v12 = _InterlockedExchangeAdd64(v6, 0xFFFFFFFFFFFFFFFFui64);
  if( (v12 & 2) != 0 && (v12 & 4) == 0 )
    ExfTryToWakePushLock((volatile INT64 *)(v4 + 24));
  KeAbPostRelease((PVOID)(v4 + 24));
  KeLeaveCriticalRegionThread((__int64)KeGetCurrentThread());
  VrpDereferenceDiffHiveEntry((PVOID)v4);
  return v10;
}

Referenced by:

VrpCleanupNamespace
VrpHandleIoctlLoadDifferencingHive
VrpHandleIoctlUnloadDifferencingHiveForHost