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