MiUnloadSystemImage

VOID __stdcall MiUnloadSystemImage(PVOID ImageHandle, UINT64 UnloadFlags){
  char v2; 
  bool v4; 
  char *v5; 
  unsigned __int64 v6; 
  _CONTROL_AREA *v7; 
  unsigned __int64 v8; 
  unsigned __int64 v9; 
  UINT64 v10; 
  POWER_SESSION_TIMEOUTS *v11; 
  unsigned int v12; 
  _LOAD_IMPORTS **v13; 
  __int64 v14; 
  int v15; 
  __int64 SessionVm; 
  MMPTE *PdeAddress; 
  _BOOL8 v18; 
  void *v19; 
  MMPTE *v20; 
  __int64 v21; 
  _MI_PARTITION *v22; 
  INT64 v23; 
  void *v24; 
  char v25; 
  char v26; 
  ULONG_PTR v27; 
  _CONTROL_AREA *v28; 
  CHAR *AnyMultiplexedVm; 
  int v30; 
  int v31; 
  _SECTION *v32; 
  void *v33; 
  void *v34; 
  UINT64 v35; 
  _CONTROL_AREA *v36; 
  INT64 v37; 
  MMPTE *v38; 
  unsigned int SessionId; 
  INT64 v40; 
  INT64 v41; 
  UINT64 NumberOfPtes; 
  _MMPTE *PointerPte; 
  UINT64 ExactPtes; 
  ULONG_PTR BugCheckParameter2; 
  __int64 v46; 
  INT64 v47[2]; 
  __int64 v48; 
  INT64 a2[2]; 
  __int128 v50; 
  __int128 v51; 
  INT64 result[26]; 
  char v53; 
  int v54; 
  _SECTION *Object; 
  v53 = UnloadFlags;
  v46 = 0i64;
  v2 = UnloadFlags;
  v48 = 0i64;
  *(_OWORD *)v47 = 0i64;
  memset((INT64)result, 0i64);
  v4 = *((_QWORD *)ImageHandle + 17) == 1i64;
  *(_OWORD *)a2 = 0i64;
  v50 = 0i64;
  v51 = 0i64;
  if( v4 )
    return;
  v5 = (char *)*((_QWORD *)ImageHandle + 6);
  BugCheckParameter2 = (ULONG_PTR)v5;
  v6 = ((unsigned __int64)ImageHandle + 160) & -(__int64)((v2 & 4) != 0);
  v7 = 0i64;
  PointerPte = MiGetPteAddress(v5);
  v8 = (unsigned __int64)*((unsigned int *)ImageHandle + 16) >> 12;
  NumberOfPtes = v8;
  Object = (_SECTION *)*((_QWORD *)ImageHandle + 14);
  LOBYTE(v9) = MiBytesToMapSystemImage((_FAST_MUTEX *)*((unsigned int *)ImageHandle + 16));
  ExactPtes = v9 >> 12;
  if( (unsigned int)MiGetSystemRegionType((UINT64)v5) == 1 )
  {
    v54 = 0;
    v13 = (_LOAD_IMPORTS **)MiSessionRemoveImage((UINT64)ImageHandle, (INT64)v47);
    if( !v13 )
      return;
    v7 = MiSectionControlArea(Object);
    if( *(_QWORD *)ImageHandle )
      ExCovReadjustUnloadedModuleEntry((__int64)ImageHandle, 0);
    v14 = *(_QWORD *)(*((_QWORD *)KeGetCurrentThread() + 23) + 1368i64);
    v15 = v2 & 1;
    if( v15 )
    {
      if( MiIsRetpolineEnabled() )
      {
        MiUnmapRetpolineStubs((INT64)ImageHandle, 0i64);
        if( (unsigned int)MiIsImageFullyRetpolined((INT64)ImageHandle) )
          KeFlushRsb();
        _mm_lfence();
      }
      SessionVm = MiGetSessionVm();
      MiDeleteSystemPagableVm(SessionVm, (__int64)v7, (unsigned __int64)PointerPte, NumberOfPtes, 3, a2);
    }
    MiReleaseSessionDriverCharges((INT64)v13);
    if( v15 )
    {
      v18 = (dword_140C4C9F0 & 0xFFF) != 0;
      if( v18 + ((unsigned int)dword_140C4C9F0 >> 12) )
        MiUnmapPatchTable((UINT64)PointerPte + 8
                                             * (ExactPtes - ((unsigned int)v18 + ((unsigned int)dword_140C4C9F0 >> 12))));
      if( (*((_DWORD *)v7 + 14) & 0x4000000) != 0 )
      {
        SessionId = MmGetSessionIdEx(*((_QWORD *)KeGetCurrentThread() + 23));
        MiDereferencePerSessionProtos((__int64 *)v7, SessionId);
      }
      MiGetPdeAddress(v5);
      v19 = (void *)v47[0];
      if( v47[0] )
        v19 = (void *)(v47[0] + 1);
      if( v19 )
        MiGetPdeAddress(v19);
      PdeAddress = MiGetPdeAddress(&v5[*((_DWORD *)ImageHandle + 16) - 1]);
      if( v47[1] )
      {
        v38 = MiGetPdeAddress((PVOID)v47[1]);
        if( v38 == PdeAddress )
          PdeAddress = (MMPTE *)((char *)PdeAddress - 8);
      }
      if( PdeAddress >= v20 )
        MiDeleteSessionPdes(v20, PdeAddress);
    }
    v21 = v48;
    if( v48 )
    {
      LODWORD(v22) = MiPartitionIdToPointer(*(_WORD *)(v14 + 430), (UINT64)PdeAddress);
      MiReturnCommit(v22, v21 - a2[1]);
      _InterlockedExchangeAdd64((volatile signed __int64 *)(v14 + 48), -v21);
    }
    v2 = v53;
    if( (v53 & 0x10) != 0 )
    {
      MiDereferenceImports(v13[11]);
      MiFreeLoadedImportList(v13[11]);
    }
    ExFreePoolWithTag(v13, 0);
    v12 = 0;
    v8 = NumberOfPtes;
  }
  else
  {
    v12 = 1;
    v54 = 1;
  }
  v4 = (*((_WORD *)ImageHandle + 54))-- == 1;
  if( !v4 )
  {
    if( !v12 && (v2 & 2) != 0 )
      VfDriverUnloadImage((_KLDR_DATA_TABLE_ENTRY *)ImageHandle);
    return;
  }
  KeCleanupImageTracepoints((UINT64)ImageHandle, v10, v11);
  if( (int)MiMarkKernelImageCfgBits((__int64)ImageHandle, 0i64) < 0 )
    KeBugCheckEx(0x1Au, 0x1015ui64, (ULONG_PTR)v5, (ULONG_PTR)ImageHandle, (*(_DWORD *)(v6 + 36) >> 8) & 1);
  if( v12 )
  {
    if( dword_140C4C9F0 )
      MiClearDriverHotPatchPtes((INT64)ImageHandle);
  }
  else
  {
    MiDeleteSessionDriverProtos((__int64 *)v7);
  }
  if( MmHasImageBeenImportOptimized() )
    MiFreeRetpolineImportInfo(v23);
  if( MiIsRetpolineEnabled() )
  {
    if( v12 && !(unsigned int)MI_IS_PHYSICAL_ADDRESS(*((PVOID *)ImageHandle + 6)) )
      MiUnmapRetpolineStubs((INT64)ImageHandle, v12);
    MiMarkKernelImageRetpolineBits((INT64)ImageHandle);
    if( (unsigned int)MiIsImageFullyRetpolined((INT64)ImageHandle) )
      KeFlushRsb();
    _mm_lfence();
  }
  if( v6 )
  {
    v24 = *(void **)(v6 + 136);
    if( v24 )
    {
      MiFreeRetpolineRelocationInformation(v24);
      *(_QWORD *)(v6 + 136) = 0i64;
    }
  }
  if( (v2 & 2) != 0 )
  {
    VfDriverUnloadImage((_KLDR_DATA_TABLE_ENTRY *)ImageHandle);
    KseDriverUnloadImage((__int64)ImageHandle);
  }
  if( !v12 )
  {
    MiReleasePrivilegedPtes();
    v8 = 0i64;
    NumberOfPtes = 0i64;
  }
  if( (v2 & 0x10) != 0 )
    MiDereferenceImports(*((_LOAD_IMPORTS **)ImageHandle + 17));
  MiFreeLoadedImportList(*((VOID **)ImageHandle + 17));
  *((_QWORD *)ImageHandle + 17) = 1i64;
  LdrUnloadAlternateResourceModule(v5);
  if( (*((_DWORD *)ImageHandle + 26) & 0x100000) != 0 )
    DbgUnLoadImageSymbolsUnicode((UNICODE_STRING *)((char *)ImageHandle + 88), v5, 0xFFFFFFFFui64);
  if( *(_QWORD *)ImageHandle && v8 )
    ExCovReadjustUnloadedModuleEntry((__int64)ImageHandle, 0);
  v25 = 0;
  v26 = 0;
  if( !v8 || (v2 & 1) == 0 )
    goto LABEL_94;
  MiRememberUnloadedDriver((UNICODE_STRING *)((char *)ImageHandle + 88), v5, ExactPtes << 12);
  v27 = 0i64;
  if( Object )
  {
    v28 = MiSectionControlArea(Object);
    v27 = (ULONG_PTR)v28;
    if( *(_QWORD *)ImageHandle )
    {
      result[0] = (INT64)v28;
      MiManageSubsectionView(result, v6, 4i64);
    }
  }
  AnyMultiplexedVm = MiGetAnyMultiplexedVm(1i64);
  if( (unsigned int)MI_IS_PHYSICAL_ADDRESS(v5) )
  {
    MiUnmapLargeDriver(v5, NumberOfPtes);
    v25 = 1;
LABEL_94:
    v32 = Object;
    goto LABEL_63;
  }
  if( v6 )
    MiUnlockDriverCode((__int64)ImageHandle);
  qword_140C4CA60 = (UNICODE_STRING *)ImageHandle;
  MiDeleteSystemPagableVm((__int64)AnyMultiplexedVm, v27, (unsigned __int64)PointerPte, NumberOfPtes, 5, a2);
  v30 = DWORD2(v50);
  v31 = a2[0];
  if( v27 )
    MiWalkEntireImage(v27, (unsigned __int64)&v46, 4, 0xFFFFFFFF);
  qword_140C4CA60 = 0i64;
  _InterlockedExchangeAdd((_DWORD *)&xmmword_140C4CA88 + 3, v31 - v30);
  v32 = Object;
  if( !Object )
  {
    MiReleasePrivilegedPtes();
    if( !(unsigned int)MiCreateSystemWsles() )
    {
      v40 = MiVaToSoftwareWsle(
              (INT64)AnyMultiplexedVm,
              (__int64)((NumberOfPtes << 28) + ((_QWORD)PointerPte << 25) - ((_QWORD)MmGetPteBase() << 25)) >> 16);
      if( ExactPtes != NumberOfPtes )
      {
        LOBYTE(v41) = 10;
        memset(v40, v41);
      }
    }
    v5 = (char *)BugCheckParameter2;
    v26 = 1;
    v25 = 0;
    v2 = v53;
    goto LABEL_94;
  }
  v5 = (char *)BugCheckParameter2;
  v25 = 0;
  v2 = v53;
LABEL_63:
  if( v54 == 1 )
  {
    if( v32 )
      MiReleasePrivilegedPtes();
    if( (v2 & 1) != 0 )
      MiReturnSystemImageCommitment(ImageHandle, (INT64)a2);
  }
  if( *(_QWORD *)ImageHandle )
    MiProcessLoaderEntry((__int64 *)ImageHandle, 0);
  if( v26 )
    MiReleaseDriverPtes(0i64, PointerPte, (unsigned int)ExactPtes);
  v33 = (void *)*((_QWORD *)ImageHandle + 10);
  if( v33 )
    ExFreePoolWithTag(v33, 0);
  if( v6 )
  {
    v34 = *(void **)(v6 + 128);
    if( v34 )
      MiFreePatchTableProtos(v34);
  }
  if( Object )
  {
    if( v6 )
    {
      v35 = *(_QWORD *)(v6 + 56);
      if( v35 )
        MiReturnResident((INT64)&MiSystemPartition, v35);
    }
    v36 = MiSectionControlArea(Object);
    v37 = (INT64)v36;
    if( !v25 && v5 != *(char **)(*(_QWORD *)v36 + 32i64) )
    {
      MiFreePrivateFixupEntryForSystemImage(v5, 1ui64);
      MiReturnSystemImageAddress(v5, *((unsigned int *)ImageHandle + 16));
    }
    if( v6 && v54 && (*(_DWORD *)(v6 + 36) & 0x80u) != 0 )
      MiReturnCrossPartitionControlAreaCharges(v37);
    MiDereferenceControlArea(v37);
    ObDereferenceObjectDeferDelete(Object);
  }
  ExFreePoolWithTag(ImageHandle, 0);
}

Referenced by:

MiApplyHotPatchToLoadedDriver
MiDereferenceImports
MmChangeImageProtection
MmLoadSystemImageEx
MmUnloadSystemImage