IopUnloadDriver

NTSTATUS __stdcall IopUnloadDriver(_UNICODE_STRING *DriverServiceName, UINT8 InvokedByPnpMgr){
  __int16 v4; 
  char PreviousMode; 
  int DriverNameFromKeyNode; 
  _DRIVER_OBJECT *v7; 
  __int64 v8; 
  void(__fastcall *DriverUnload)(_DRIVER_OBJECT *); 
  __int64 v11; 
  int v12; 
  unsigned __int64 v13; 
  unsigned __int64 v14; 
  void *PoolWithQuota_2; 
  NTSTATUS v16; 
  _ADAPTER_OBJECT *v17; 
  UINT64 Create; 
  PVOID Handle; 
  _HANDLE v20[2]; 
  VOID *Src[2]; 
  _UNICODE_STRING DriverName; 
  PVOID P; 
  _OBJECT_ATTRIBUTES ObjectAttributes; 
  _WORK_QUEUE_ITEM WorkItem[3]; 
  UINT8 unloadDriver; 
  PVOID Object; 

  *(_OWORD *)Src = 0i64;
  P = 0i64;
  *(&ObjectAttributes.Length + 1) = 0;
  *(&ObjectAttributes.Attributes + 1) = 0;
  Handle = 0i64;
  *(_DWORD *)(&DriverName.MaximumLength + 1) = 0;
  *(_QWORD *)v20 = 0i64;
  unloadDriver = 0;
  LOBYTE(v4) = 0;
  PreviousMode = KeGetCurrentThread()->PreviousMode;
  if( !PreviousMode || InvokedByPnpMgr )
  {
    PnpDiagnosticTraceObject(&KMPnPEvt_DriverUnload_Start, &DriverServiceName->Length);
    DriverName.Buffer = 0i64;
    *(_DWORD *)&DriverName.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, &DriverName);
      ObCloseHandle(Handle, 0);
      if( DriverNameFromKeyNode >= 0 )
      {
        ObjectAttributes.Length = 48;
        ObjectAttributes.RootDirectory = 0i64;
        ObjectAttributes.Attributes = 576;
        ObjectAttributes.ObjectName = &DriverName;
        *(_OWORD *)&ObjectAttributes.SecurityDescriptor = 0i64;
        LODWORD(Create) = 1;
        DriverNameFromKeyNode = ObOpenObjectByName(
                                  &ObjectAttributes,
                                  IoDriverObjectType,
                                  0,
                                  0i64,
                                  Create,
                                  0i64,
                                  (VOID **)v20);
        if( DriverNameFromKeyNode >= 0 )
        {
          Object = 0i64;
          DriverNameFromKeyNode = ObReferenceObjectByHandle(*(VOID **)v20, 0i64, IoDriverObjectType, 0, &Object, 0i64);
          ObCloseHandle(*(VOID **)v20, 0);
          if( DriverNameFromKeyNode >= 0 )
          {
            v7 = (_DRIVER_OBJECT *)Object;
            LODWORD(v8) = RtlImageNtHeader(*((_QWORD *)Object + 3));
            v4 = *(_WORD *)(v8 + 70);
            if( v7->DriverUnload && v7->DriverSection )
            {
              if( InvokedByPnpMgr || PnpIsLegacyDriver((__int64)v7) )
              {
                DriverNameFromKeyNode = IopCheckUnloadDriver(v7, &unloadDriver);
                if( (int)(DriverNameFromKeyNode + 0x80000000) >= 0 && DriverNameFromKeyNode != -1073741808 )
                {
                  if( unloadDriver )
                  {
                    if( KeGetCurrentThread()->ApcState.Process == PsInitialSystemProcess )
                    {
                      DriverUnload = v7->DriverUnload;
                      v7 = (_DRIVER_OBJECT *)Object;
                      DriverUnload((_DRIVER_OBJECT *)Object);
                      EtwTiLogDriverObjectUnLoad((INT64)&v7->DriverName);
                    }
                    else
                    {
                      memset(WorkItem, 0i64, 0x50u);
                      KeInitializeEvent((INT64)&WorkItem[1], 0, 0);
                      v7 = (_DRIVER_OBJECT *)Object;
                      WorkItem[1].Parameter = Object;
                      WorkItem[0].WorkerRoutine = (void(__fastcall *)(void *))IopLoadUnloadDriver;
                      WorkItem[0].Parameter = WorkItem;
                      WorkItem[0].List.Flink = 0i64;
                      ExQueueWorkItem(WorkItem, DelayedWorkQueue);
                      KeWaitForSingleObject((UINT64)&WorkItem[1], 0, 0, 0, 0i64);
                    }
                    IopCleanupNotifications(v7, v7);
                    ObMakeTemporaryObject(v7);
                    HalPutDmaAdapter((PADAPTER_OBJECT)v7);
                  }
                  HalPutDmaAdapter((PADAPTER_OBJECT)v7);
                  DriverNameFromKeyNode = 0;
                }
                goto LABEL_17;
              }
            }
            else
            {
              v17 = (_ADAPTER_OBJECT *)v7;
            }
            HalPutDmaAdapter(v17);
            DriverNameFromKeyNode = -1073741808;
          }
        }
      }
    }
LABEL_17:
    PnpDiagnosticTraceDriverFullInfo(
      &KMPnPEvt_DriverUnload_Stop,
      &DriverServiceName->Length,
      DriverNameFromKeyNode,
      (__int64)&DriverName,
      v4);
    if( DriverName.Buffer )
      ExFreePoolWithTag(DriverName.Buffer, 0);
    return DriverNameFromKeyNode;
  }
  if( !SeSinglePrivilegeCheck(*(_QWORD *)&SeLoadDriverPrivilege, PreviousMode) )
    return -1073741727;
  v11 = 0x7FFFFFFF0000i64;
  if( (unsigned __int64)DriverServiceName < 0x7FFFFFFF0000i64 )
    v11 = (__int64)DriverServiceName;
  v12 = *(_DWORD *)v11;
  LODWORD(Src[0]) = v12;
  v13 = *(_QWORD *)(v11 + 8);
  Src[1] = (VOID *)v13;
  if( !(_WORD)v12 )
    return -1073741811;
  if( (v13 & 1) != 0 )
    ExRaiseDatatypeMisalignment();
  v14 = v13 + (unsigned __int16)v12;
  if( v14 > 0x7FFFFFFF0000i64 || v14 < v13 )
    MEMORY[0x7FFFFFFF0000] = 0;
  PoolWithQuota_2 = IopVerifierExAllocatePoolWithQuota_2(v13, LOWORD(Src[0]));
  P = PoolWithQuota_2;
  memmove(PoolWithQuota_2, Src[1], LOWORD(Src[0]));
  Src[1] = PoolWithQuota_2;
  v16 = ZwUnloadDriver((_UNICODE_STRING *)Src);
  ExFreePoolWithTag(PoolWithQuota_2, 0);
  return v16;
}

Referenced by:

NtUnloadDriver
PipUnloadEarlyLaunchDrivers
PnpUnloadAttachedDriver