@Doron_Holan said:
The doc page you are referring to is describing unload behavior for pnp drivers. The rules are different for a non pnp driver.
To me it looks like this page is for both.
Still, unload isn’t called for non-pnp driver as long as control device is opened by application. Maybe it is not how it should work, but it’s how it works in fact.
I just checked this with non-pnp driver registered by sc create.
My application opens cdo.
I try to unload driver with net stop
DriverUnload is not called
#include <wdm.h>
#include <wdmsec.h>
#include <common.h>
PDEVICE_OBJECT cdo{ nullptr };
void unload(PDRIVER_OBJECT)
{
UNICODE_STRING cdoDosName = RTL_CONSTANT_STRING(Common::cdoNameDOS);
IoDeleteSymbolicLink(&cdoDosName);
IoDeleteDevice(cdo);
cdo = nullptr;
}
NTSTATUS dispatch(PDEVICE_OBJECT, PIRP irp)
{
const IO_STACK_LOCATION* sl{ IoGetCurrentIrpStackLocation(irp) };
switch (sl->MajorFunction)
{
case IRP_MJ_CREATE:
KdPrint((“IRP_MJ_CREATE\n”));
break;
case IRP_MJ_CLEANUP:
KdPrint((“IRP_MJ_CLEANUP\n”));
break;
case IRP_MJ_CLOSE:
KdPrint((“IRP_MJ_CLOSE\n”));
break;
}
irp->IoStatus.Status = STATUS_SUCCESS;
irp->IoStatus.Information = 0;
IoCompleteRequest(irp, IO_NO_INCREMENT);
return STATUS_SUCCESS;
}
extern “C” NTSTATUS DriverEntry(PDRIVER_OBJECT driver, PUNICODE_STRING)
{
driver->DriverUnload = unload;
driver->MajorFunction[IRP_MJ_CREATE] = driver->MajorFunction[IRP_MJ_CLEANUP] = driver->MajorFunction[IRP_MJ_CLOSE] = dispatch;
UNICODE_STRING deviceName = RTL_CONSTANT_STRING(Common::cdoNameNT);
NTSTATUS stat{ WdmlibIoCreateDeviceSecure(driver,
0,
&deviceName,
FILE_DEVICE_UNKNOWN,
FILE_DEVICE_SECURE_OPEN,
FALSE,
&SDDL_DEVOBJ_SYS_ALL_ADM_ALL,
nullptr,
&cdo) };
if (NT_SUCCESS(stat))
{
UNICODE_STRING cdoDosName = RTL_CONSTANT_STRING(Common::cdoNameDOS);
stat = IoCreateSymbolicLink(&cdoDosName, &deviceName);
if (!NT_SUCCESS(stat))
{
IoDeleteDevice(cdo);
cdo = nullptr;
}
}
else
{
cdo = nullptr;
}
return stat;
}