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