IopUnloadDriver

NTSTATUS __stdcall IopUnloadDriver(UNICODE_STRING *DriverServiceName, UINT8 InvokedByPnpMgr){
  int v4; 
  INT8 v5; 
  int DriverNameFromKeyNode; 
  DRIVER_OBJECT *v7; 
  IMAGE_NT_HEADERS *v8; 
  void(__fastcall *DriverUnload)(_DRIVER_OBJECT *); 
  INT64 v10; 
  EVENT_DESCRIPTOR *v11; 
  __int64 v13; 
  int v14; 
  unsigned __int64 v15; 
  unsigned __int64 v16; 
  void *PoolWithQuota_2; 
  NTSTATUS v18; 
  struct _DMA_ADAPTER *v19; 
  PVOID *Object; 
  HANDLE Handle; 
  HANDLE v22; 
  void *Src[2]; 
  struct _UNICODE_STRING Destination; 
  PVOID P; 
  int v26[2]; 
  __int64 v27; 
  struct _UNICODE_STRING *p_Destination; 
  int v29; 
  int v30; 
  __int128 v31; 
  struct _WORK_QUEUE_ITEM WorkItem; 
  struct _KEVENT Event; 
  PVOID v34; 
  UINT8 unloadDriver; 
  PVOID IoObject; 
  *(_OWORD *)Src = 0i64;
  P = 0i64;
  v26[1] = 0;
  v30 = 0;
  Handle = 0i64;
  *(_DWORD *)(&Destination.MaximumLength + 1) = 0;
  v22 = 0i64;
  unloadDriver = 0;
  v4 = 0;
  v5 = *((_BYTE *)KeGetCurrentThread() + 562);
  if( !v5 || InvokedByPnpMgr )
  {
    PnpDiagnosticTraceObject(&KMPnPEvt_DriverUnload_Start, DriverServiceName);
    Destination.Buffer = 0i64;
    *(_DWORD *)&Destination.Length = 0;
    if( PsIsCurrentThreadInServerSilo() )
    {
      DbgPrint("Server Silo attempting to unload driver %wZ\n", DriverServiceName);
      return -1073741727;
    }
    DriverNameFromKeyNode = IopOpenRegistryKey(&Handle, 0i64, DriverServiceName, 0x20019ui64, 0);
    if( DriverNameFromKeyNode >= 0 )
    {
      DriverNameFromKeyNode = IopGetDriverNameFromKeyNode(Handle, &Destination);
      ObCloseHandle(Handle, 0);
      if( DriverNameFromKeyNode >= 0 )
      {
        v26[0] = 48;
        v27 = 0i64;
        v29 = 576;
        p_Destination = &Destination;
        v31 = 0i64;
        DriverNameFromKeyNode = ObOpenObjectByName((__int64)v26, (__int64)IoDriverObjectType, 0, 0i64, 1u, 0i64, &v22);
        if( DriverNameFromKeyNode >= 0 )
        {
          IoObject = 0i64;
          DriverNameFromKeyNode = ObReferenceObjectByHandle(v22, 0, IoDriverObjectType, 0, &IoObject, 0i64);
          ObCloseHandle(v22, 0);
          if( DriverNameFromKeyNode >= 0 )
          {
            v7 = (DRIVER_OBJECT *)IoObject;
            v8 = RtlImageNtHeader(*((PVOID *)IoObject + 3));
            v4 = v8->OptionalHeader.MinorImageVersion | (v8->OptionalHeader.MajorImageVersion << 16);
            if( v7->DriverUnload && v7->DriverSection )
            {
              if( InvokedByPnpMgr || (unsigned int)PnpIsLegacyDriver(v7) )
              {
                DriverNameFromKeyNode = IopCheckUnloadDriver(v7, &unloadDriver);
                if( (int)(DriverNameFromKeyNode + 0x80000000) >= 0 && DriverNameFromKeyNode != -1073741808 )
                {
                  if( unloadDriver )
                  {
                    if( *((PEPROCESS *)KeGetCurrentThread() + 23) == PsInitialSystemProcess )
                    {
                      DriverUnload = v7->DriverUnload;
                      v7 = (DRIVER_OBJECT *)IoObject;
                      DriverUnload((_DRIVER_OBJECT *)IoObject);
                      EtwTiLogDriverObjectUnLoad(&v7->DriverName.Length, v10, v11);
                    }
                    else
                    {
                      memset((INT64)&WorkItem, 0i64);
                      KeInitializeEvent(&Event, NotificationEvent, 0);
                      v7 = (DRIVER_OBJECT *)IoObject;
                      v34 = IoObject;
                      WorkItem.WorkerRoutine = (void(__fastcall *)(void *))IopLoadUnloadDriver;
                      WorkItem.Parameter = &WorkItem;
                      WorkItem.List.Flink = 0i64;
                      ExQueueWorkItem(&WorkItem, DelayedWorkQueue);
                      KeWaitForSingleObject(&Event, Executive, 0, 0, 0i64);
                    }
                    IopCleanupNotifications(v7, v7);
                    ObMakeTemporaryObject(v7);
                    HalPutDmaAdapter((PADAPTER_OBJECT)v7);
                  }
                  HalPutDmaAdapter((PADAPTER_OBJECT)v7);
                  DriverNameFromKeyNode = 0;
                }
                goto LABEL_17;
              }
            }
            else
            {
              v19 = (struct _DMA_ADAPTER *)v7;
            }
            HalPutDmaAdapter(v19);
            DriverNameFromKeyNode = -1073741808;
          }
        }
      }
    }
LABEL_17:
    LODWORD(Object) = v4;
    PnpDiagnosticTraceDriverFullInfo(
      &KMPnPEvt_DriverUnload_Stop,
      DriverServiceName,
      (unsigned int)DriverNameFromKeyNode,
      &Destination,
      (UINT64)Object);
    if( Destination.Buffer )
      ExFreePoolWithTag(Destination.Buffer, 0);
    return DriverNameFromKeyNode;
  }
  if( !SeSinglePrivilegeCheck(*(_QWORD *)&SeLoadDriverPrivilege, v5) )
    return -1073741727;
  v13 = 0x7FFFFFFF0000i64;
  if( (unsigned __int64)DriverServiceName < 0x7FFFFFFF0000i64 )
    v13 = (__int64)DriverServiceName;
  v14 = *(_DWORD *)v13;
  LODWORD(Src[0]) = v14;
  v15 = *(_QWORD *)(v13 + 8);
  Src[1] = (void *)v15;
  if( !(_WORD)v14 )
    return -1073741811;
  if( (v15 & 1) != 0 )
    ExRaiseDatatypeMisalignment();
  v16 = v15 + (unsigned __int16)v14;
  if( v16 > 0x7FFFFFFF0000i64 || v16 < v15 )
    MEMORY[0x7FFFFFFF0000] = 0;
  PoolWithQuota_2 = IopVerifierExAllocatePoolWithQuota_2(v15, LOWORD(Src[0]));
  P = PoolWithQuota_2;
  memmove((UINT8 *)PoolWithQuota_2, (UINT8 *)Src[1], LOWORD(Src[0]));
  Src[1] = PoolWithQuota_2;
  v18 = ZwUnloadDriver((UNICODE_STRING *)Src);
  ExFreePoolWithTag(PoolWithQuota_2, 0);
  return v18;
}

Referenced by:

NtUnloadDriver
PipUnloadEarlyLaunchDrivers
PnpUnloadAttachedDriver