FsRtlNotifyFilterChangeDirectory

VOID __stdcall FsRtlNotifyFilterChangeDirectory(
        PNOTIFY_SYNC NotifySync,
        PLIST_ENTRY NotifyList,
        PVOID FsContext,
        PSTRING FullDirectoryName,
        BOOL WatchTree,
        BOOL IgnoreBuffer,
        UINT32 CompletionFilter,
        PIRP NotifyIrp,
        PCHECK_FOR_TRAVERSE_ACCESS TraverseCallback,
        PSECURITY_SUBJECT_CONTEXT SubjectContext,
        PFILTER_REPORT_CHANGE FilterCallback){
  PVOID v12; 
  _ETHREAD *CurrentThread; 
  unsigned int v16; 
  __int64 v17; 
  LIST_ENTRY *v18; 
  unsigned int *PoolWithTag; 
  __int16 Blink; 
  UINT64 v21; 
  _QWORD *v22; 
  VOID **v23; 
  _LIST_ENTRY *v24; 
  _LIST_ENTRY *v25; 
  __int16 v26; 
  INT64 v28; 
  v12 = FsContext;
  if( NotifyList->Flink == NotifyList && !NotifyIrp )
    return;
  CurrentThread = (_ETHREAD *)KeGetCurrentThread();
  if( CurrentThread != *((_ETHREAD **)NotifySync + 7) )
  {
    ExAcquireFastMutexUnsafe((PFAST_MUTEX)NotifySync);
    *((_QWORD *)NotifySync + 7) = CurrentThread;
    v12 = FsContext;
  }
  LOBYTE(v16) = 1;
  ++*((_DWORD *)NotifySync + 16);
  if( !NotifyIrp )
  {
    FsRtlCheckNotifyForDelete(NotifyList, v12);
    goto LABEL_36;
  }
  v17 = *((_QWORD *)NotifyIrp + 23);
  *((_DWORD *)NotifyIrp + 12) = 0;
  *((_QWORD *)NotifyIrp + 7) = 0i64;
  if( (*(_DWORD *)(*(_QWORD *)(v17 + 48) + 80i64) & 0x4000) != 0 )
    goto LABEL_22;
  v18 = FsRtlIsNotifyOnList(NotifyList, v12);
  PoolWithTag = (unsigned int *)v18;
  if( v18 )
  {
    Blink = (__int16)v18[4].Blink;
    if( (Blink & 4) == 0 )
    {
      if( (Blink & 0x20) == 0 )
      {
        if( ((unsigned __int8)Blink & (unsigned __int8)(v16 + 1)) != 0 && (Blink & 8) == 0 )
        {
          *((_WORD *)PoolWithTag + 36) = Blink & 0xFFFD;
          *(_BYTE *)(*((_QWORD *)NotifyIrp + 23) + 3i64) |= v16;
          *((_DWORD *)NotifyIrp + 12) = 268;
          goto LABEL_23;
        }
        v21 = PoolWithTag[26];
        if( (_DWORD)v21 && (Blink & 8) == 0 )
        {
          *((_QWORD *)PoolWithTag + 13) = 0i64;
          LODWORD(v28) = 0;
          FsRtlNotifyCompleteIrp(NotifyIrp, (INT64)PoolWithTag, v21, 0i64, v28);
          goto LABEL_36;
        }
        goto LABEL_11;
      }
      *(_BYTE *)(v17 + 3) |= v16;
      *((_DWORD *)NotifyIrp + 12) = -1073741738;
LABEL_23:
      IofCompleteRequest(NotifyIrp, v16);
      goto LABEL_36;
    }
LABEL_22:
    *(_BYTE *)(v17 + 3) |= v16;
    *((_DWORD *)NotifyIrp + 12) = 267;
    goto LABEL_23;
  }
  PoolWithTag = (unsigned int *)ExAllocatePoolWithTag((_POOL_TYPE)17, 0x98ui64, 0x4E725346ui64);
  memset((INT64)PoolWithTag, 0i64);
  *(_QWORD *)PoolWithTag = NotifySync;
  *((_QWORD *)PoolWithTag + 1) = FsContext;
  *((_QWORD *)PoolWithTag + 16) = *(_QWORD *)(*(_QWORD *)(v17 + 48) + 24i64);
  *((_QWORD *)PoolWithTag + 2) = TraverseCallback;
  *((_QWORD *)PoolWithTag + 3) = SubjectContext;
  SubjectContext = 0i64;
  *((_QWORD *)PoolWithTag + 8) = FilterCallback;
  *((_QWORD *)PoolWithTag + 17) = FullDirectoryName;
  *((_QWORD *)PoolWithTag + 7) = PoolWithTag + 12;
  *((_QWORD *)PoolWithTag + 6) = PoolWithTag + 12;
  v16 = 1;
  if( WatchTree )
    *((_WORD *)PoolWithTag + 36) |= 1u;
  if( FullDirectoryName )
  {
    v26 = 2;
    if( FullDirectoryName->Length < 2u || FullDirectoryName->Buffer[1] )
    {
      *((_BYTE *)PoolWithTag + 144) = 1;
      v26 = 1;
    }
    else
    {
      *((_BYTE *)PoolWithTag + 144) = 2;
    }
    if( FullDirectoryName->Length == v26 )
      *((_WORD *)PoolWithTag + 36) |= 0x10u;
  }
  else
  {
    *((_BYTE *)PoolWithTag + 144) = 1;
  }
  PoolWithTag[19] = CompletionFilter;
  if( !IgnoreBuffer )
    PoolWithTag[24] = *(_DWORD *)(v17 + 8);
  *((_QWORD *)PoolWithTag + 15) = *(_QWORD *)(*((_QWORD *)NotifyIrp + 19) + 544i64);
  v24 = (_LIST_ENTRY *)(PoolWithTag + 8);
  v25 = NotifyList->Blink;
  if( v25->Flink != NotifyList )
LABEL_35:
    __fastfail(3u);
  v24->Flink = NotifyList;
  *((_QWORD *)PoolWithTag + 5) = v25;
  v25->Flink = v24;
  NotifyList->Blink = v24;
  PoolWithTag[28] = 1;
  v17 = *((_QWORD *)NotifyIrp + 23);
LABEL_11:
  *((_QWORD *)NotifyIrp + 7) = PoolWithTag;
  *(_BYTE *)(v17 + 3) |= v16;
  v22 = (_QWORD *)((char *)NotifyIrp + 168);
  v23 = (VOID **)*((_QWORD *)PoolWithTag + 7);
  if( *v23 != PoolWithTag + 12 )
    goto LABEL_35;
  *v22 = PoolWithTag + 12;
  *((_QWORD *)NotifyIrp + 22) = v23;
  *v23 = v22;
  *((_QWORD *)PoolWithTag + 7) = v22;
  _InterlockedAdd((volatile signed __int32 *)PoolWithTag + 28, v16);
  FsRtlNotifySetCancelRoutine((__int64)NotifyIrp, 0i64);
LABEL_36:
  if( (*((_DWORD *)NotifySync + 16))-- == 1 )
  {
    *((_QWORD *)NotifySync + 7) = 0i64;
    ExReleaseFastMutexUnsafe((PFAST_MUTEX)NotifySync);
  }
  if( SubjectContext )
  {
    if( FullDirectoryName )
    {
      SeReleaseSubjectContext(SubjectContext);
      ExFreePoolWithTag(SubjectContext, 0);
    }
  }
}

Referenced by:

FsRtlNotifyChangeDirectory
FsRtlNotifyFullChangeDirectory