EmpClientRuleRegisterNotification

INT64 __fastcall EmpClientRuleRegisterNotification(PVOID Object, INT64 a2, UINT64 a3, CHAR **a4){
  __int64 v5; 
  _QWORD *PoolWithTag; 
  unsigned int v9; 
  VOID *v10; 
  __int64 v11; 
  __int64 v12; 
  const GUID *v13; 
  SINGLE_LIST_ENTRY *v14; 
  volatile signed __int32 *v15; 
  __int64 v16; 
  __int64 v17; 
  volatile signed __int32 *v18; 
  __int64 v19; 
  _QWORD *v20; 
  _QWORD *v21; 
  char *v22; 
  char *v23; 
  __int64 v24; 
  __int64 v25; 
  volatile signed __int32 *v26; 
  v5 = (unsigned int)a3;
  PoolWithTag = 0i64;
  v9 = 0;
  ExAcquirePushLockExclusiveEx((UINT64)&EmpDatabaseLock, 0i64);
  if( a4 && (_DWORD)v5 && a2 )
  {
    PoolWithTag = ExAllocatePoolWithTag(PagedPool, 0x18ui64, 0x6C634D45ui64);
    if( !PoolWithTag )
    {
      v9 = -1073741670;
      goto LABEL_33;
    }
    v10 = ExAllocatePoolWithTag(PagedPool, (unsigned int)(40 * v5), 0x6C634D45ui64);
    PoolWithTag[1] = v10;
    if( !v10 )
    {
      v9 = -1073741670;
      goto LABEL_23;
    }
    memset((INT64)v10, 0i64);
    v11 = 0i64;
    *((_DWORD *)PoolWithTag + 4) = v5;
    while( 1 )
    {
      v12 = (unsigned int)v11 + 2 * v11;
      v13 = *(const GUID **)(a2 + 8 * v12);
      if( !v13 || !*(_QWORD *)(a2 + 8 * v12 + 8) )
        break;
      v14 = EmpSearchRuleDatabase(v13);
      if( !v14 || (v15 = (volatile signed __int32 *)EmpSearchTargetRuleList((__int64)v14), (v18 = v15) == 0i64) )
      {
        v9 = -1073741275;
        goto LABEL_23;
      }
      v19 = (unsigned int)v11 + 4 * v11;
      *(_QWORD *)(PoolWithTag[1] + 8 * v19) = v15;
      *(_QWORD *)(PoolWithTag[1] + 8 * v19 + 8) = *(_QWORD *)(a2 + 8 * v17 + 8);
      *(_QWORD *)(PoolWithTag[1] + 8 * v19 + 16) = *(_QWORD *)(a2 + 8 * v17 + 16);
      v20 = *(_QWORD **)(v16 + 88);
      v21 = (_QWORD *)(PoolWithTag[1] + 24i64 + 8 * v19);
      if( *v20 != v16 + 80 )
        __fastfail(3u);
      *v21 = v16 + 80;
      v21[1] = v20;
      *v20 = v21;
      *(_QWORD *)(v16 + 88) = v21;
      if( _InterlockedIncrement(v18) == 1 )
        EmpQueueRuleUpdateState(v16, 0i64);
      v11 = (unsigned int)(v11 + 1);
      if( (unsigned int)v11 >= (unsigned int)v5 )
      {
        if( Object )
          ObfReferenceObject(Object);
        *PoolWithTag = Object;
        *a4 = (CHAR *)PoolWithTag;
        goto LABEL_33;
      }
    }
  }
  v9 = -1073741811;
LABEL_23:
  if( PoolWithTag )
  {
    v22 = (char *)PoolWithTag[1];
    if( v22 )
    {
      if( (_DWORD)v5 )
      {
        v23 = (char *)PoolWithTag[1];
        v24 = 0i64;
        v25 = v5;
        do
        {
          v26 = *(volatile signed __int32 **)&v22[v24];
          if( v26 )
          {
            _InterlockedAdd(v26, 0xFFFFFFFF);
            v22 = (char *)PoolWithTag[1];
            v23 = v22;
          }
          v24 += 40i64;
          --v25;
        }
        while( v25 );
        v22 = v23;
      }
      ExFreePoolWithTag(v22, 0x6C634D45u);
    }
    ExFreePoolWithTag(PoolWithTag, 0x6C634D45u);
  }
LABEL_33:
  if( (_InterlockedExchangeAdd64((volatile signed __int64 *)&EmpDatabaseLock, 0xFFFFFFFFFFFFFFFFui64) & 6) == 2 )
    ExfTryToWakePushLock((volatile INT64 *)&EmpDatabaseLock);
  KeAbPostRelease(&EmpDatabaseLock);
  return v9;
}

Referenced by:

EmClientRuleRegisterNotification