preventing driver unload

I have a set of 3 drivers (bus driver which enumerates devices for the
other 2 drivers, which are a scsiport and an ndis device driver) and I
want to make sure that the drivers can never ever be unloaded. I am
finding that when doing an upgrade, the bus driver and scsiport drivers
cannot be unloaded as they are controlling system devices, but the ndis
driver gets unloaded and the new version loads which sometimes breaks
because some updates are not backwards compatible.

So I want to make all the drivers un-unloadable. Any suggestions as to
how I might do this? I tried an ObReferenceObject on the driver object
with no matching obDereferenceObject, but that doesn’t appear to work.

I thought I’d asked this before, but a google of osronline for ‘unload’
shows no such thing…

James

James Harper wrote:

I have a set of 3 drivers (bus driver which enumerates devices for the
other 2 drivers, which are a scsiport and an ndis device driver) and I
want to make sure that the drivers can never ever be unloaded. I am
finding that when doing an upgrade, the bus driver and scsiport drivers
cannot be unloaded as they are controlling system devices, but the ndis
driver gets unloaded and the new version loads which sometimes breaks
because some updates are not backwards compatible.

So I want to make all the drivers un-unloadable. Any suggestions as to
how I might do this? I tried an ObReferenceObject on the driver object
with no matching obDereferenceObject, but that doesn’t appear to work.

I thought I’d asked this before, but a google of osronline for ‘unload’
shows no such thing…

James

Maybe the NDIS driver instead should check *on load* that it is
compatible with your other components. Otherwise it won’t start, bingo.

– pa

>

James Harper wrote:
> I have a set of 3 drivers (bus driver which enumerates devices for
the
> other 2 drivers, which are a scsiport and an ndis device driver) and
I
> want to make sure that the drivers can never ever be unloaded. I am
> finding that when doing an upgrade, the bus driver and scsiport
drivers
> cannot be unloaded as they are controlling system devices, but the
ndis
> driver gets unloaded and the new version loads which sometimes
breaks
> because some updates are not backwards compatible.
>
> So I want to make all the drivers un-unloadable. Any suggestions as
to
> how I might do this? I tried an ObReferenceObject on the driver
object
> with no matching obDereferenceObject, but that doesn’t appear to
work.
>
> I thought I’d asked this before, but a google of osronline for
‘unload’
> shows no such thing…
>
> James
>

Maybe the NDIS driver instead should check *on load* that it is
compatible with your other components. Otherwise it won’t start,
bingo.

What is windows behaviour on upgrade then? I would have thought it would
be:
. Shut down devices for v1 driver
. Unload v1 driver
. Load v2 driver
. Try and start v2 devices

If the v2 devices don’t load due to my failed compatibility check, what
happens? The outcome I’m afraid of here is that the computer is left
with no network adapters.

James

… or maybe you ought to re-think how fragile you are making your
down-stack device interfaces if you frequently hit the situation where the
interface between something as straight forward as a virtual NDIS miniport
driver and the services offered by its PDO enumerator (your bus driver)
change in breaking ways.

You should *at least* do as Pavel has suggested - version your interfaces so
that your virtual device drivers (the NDIS one in this case) can fail
gracefully by discovering that the interface is an incompatible version.

Good Luck,
Dave Cattley

-----Original Message-----
From: xxxxx@lists.osr.com
[mailto:xxxxx@lists.osr.com] On Behalf Of Pavel A.
Sent: Thursday, May 14, 2009 6:42 AM
To: Windows System Software Devs Interest List
Subject: Re:[ntdev] preventing driver unload

James Harper wrote:

I have a set of 3 drivers (bus driver which enumerates devices for the
other 2 drivers, which are a scsiport and an ndis device driver) and I
want to make sure that the drivers can never ever be unloaded. I am
finding that when doing an upgrade, the bus driver and scsiport drivers
cannot be unloaded as they are controlling system devices, but the ndis
driver gets unloaded and the new version loads which sometimes breaks
because some updates are not backwards compatible.

So I want to make all the drivers un-unloadable. Any suggestions as to
how I might do this? I tried an ObReferenceObject on the driver object
with no matching obDereferenceObject, but that doesn’t appear to work.

I thought I’d asked this before, but a google of osronline for ‘unload’
shows no such thing…

James

Maybe the NDIS driver instead should check *on load* that it is
compatible with your other components. Otherwise it won’t start, bingo.

– pa


NTDEV is sponsored by OSR

For our schedule of WDF, WDM, debugging and other seminars visit:
http://www.osr.com/seminars

To unsubscribe, visit the List Server section of OSR Online at
http://www.osronline.com/page.cfm?name=ListServer

Yes, that is what Windows does.

Then design your Vn+1 network driver to work with either Vn or Vn+1 bus
driver.

Or change the PnP device Id for the child devices enumerated by your bus
driver each time you break compatibility so that the new driver does not
install on the old device.

Think about it. You have given Windows a newer driver that you claim
supports the PnP ID enumerated by a bus driver in the system yet the new
driver does *not* support this device. You have lied to the system. Shit
hits the fan. What did you expect?

Either build the FDO drivers so they robustly support down-level bus (PDO)
device interfaces or change the device ID so that the bus does not enumerate
a ‘new’ PDO (DevId) until after reboot.

Good Luck,
Dave Cattley

-----Original Message-----
From: xxxxx@lists.osr.com
[mailto:xxxxx@lists.osr.com] On Behalf Of James Harper
Sent: Thursday, May 14, 2009 9:10 AM
To: Windows System Software Devs Interest List
Subject: RE: [ntdev] preventing driver unload

James Harper wrote:
> I have a set of 3 drivers (bus driver which enumerates devices for
the
> other 2 drivers, which are a scsiport and an ndis device driver) and
I
> want to make sure that the drivers can never ever be unloaded. I am
> finding that when doing an upgrade, the bus driver and scsiport
drivers
> cannot be unloaded as they are controlling system devices, but the
ndis
> driver gets unloaded and the new version loads which sometimes
breaks
> because some updates are not backwards compatible.
>
> So I want to make all the drivers un-unloadable. Any suggestions as
to
> how I might do this? I tried an ObReferenceObject on the driver
object
> with no matching obDereferenceObject, but that doesn’t appear to
work.
>
> I thought I’d asked this before, but a google of osronline for
‘unload’
> shows no such thing…
>
> James
>

Maybe the NDIS driver instead should check *on load* that it is
compatible with your other components. Otherwise it won’t start,
bingo.

What is windows behaviour on upgrade then? I would have thought it would
be:
. Shut down devices for v1 driver
. Unload v1 driver
. Load v2 driver
. Try and start v2 devices

If the v2 devices don’t load due to my failed compatibility check, what
happens? The outcome I’m afraid of here is that the computer is left
with no network adapters.

James


NTDEV is sponsored by OSR

For our schedule of WDF, WDM, debugging and other seminars visit:
http://www.osr.com/seminars

To unsubscribe, visit the List Server section of OSR Online at
http://www.osronline.com/page.cfm?name=ListServer

>

Yes, that is what Windows does.

Then design your Vn+1 network driver to work with either Vn or Vn+1
bus
driver.

Or change the PnP device Id for the child devices enumerated by your
bus
driver each time you break compatibility so that the new driver does
not
install on the old device.

Think about it. You have given Windows a newer driver that you claim
supports the PnP ID enumerated by a bus driver in the system yet the
new
driver does *not* support this device. You have lied to the system.
Shit
hits the fan. What did you expect?

Either build the FDO drivers so they robustly support down-level bus
(PDO)
device interfaces or change the device ID so that the bus does not
enumerate
a ‘new’ PDO (DevId) until after reboot.

I have indeed tried incorporating a version id (interface/api version
number) into the pnp id before. It’s a royal pain when the driver is
unsigned though, as windows gives you prompts etc and again you have no
network on reboot until the driver is approved by the user. Also, I have
to manually update my .inx file every time I make an interface change. I
did have problems booting too as windows seemed to have trouble with the
boot device with the new pnp id. That may have been to do with my
signing issues though.

But what you say is pretty sound. I hadn’t thought about it that way
before. Despite the pain that goes with it, it does appear to be the
‘correct’ thing to do.

The fact that no one has piped up with “to prevent your driver
unloading, do ” also suggests to me that it can’t be done.
Probably to make sure that (like I was hoping to) nobody takes the easy
(but incorrect) path.

Thanks for the input

James

>

I have indeed tried incorporating a version id (interface/api version
number) into the pnp id before. It’s a royal pain when the driver is
unsigned though, as windows gives you prompts etc and again you have
no
network on reboot until the driver is approved by the user. Also, I
have
to manually update my .inx file every time I make an interface change.
I
did have problems booting too as windows seemed to have trouble with
the
boot device with the new pnp id. That may have been to do with my
signing issues though.

I just tried implementing that idea again, with slightly disasterous
results. This time the network driver unloads, but windows fails to
reload it again, so I’m left with no network at all. This will never do!

I am keeping the same service name and .sys name through the upgrade, is
that going to cause problems? I changed the pnp id to xen\vif_v1 instead
of xen\vif for this update, but the driver name remains xennet.sys and
the service remains xennet. Do I need to change those?

Thanks

James

My memory is a bit fuzzy on this point as it has been awhile, but doesn’t changing the hwid invalidate all the users network configuration in the guest when a completely new hardware devnode is materialized?

  • S

-----Original Message-----
From: James Harper
Sent: Thursday, May 14, 2009 17:45
To: Windows System Software Devs Interest List
Subject: RE: [ntdev] preventing driver unload

>
> I have indeed tried incorporating a version id (interface/api version
> number) into the pnp id before. It’s a royal pain when the driver is
> unsigned though, as windows gives you prompts etc and again you have
no
> network on reboot until the driver is approved by the user. Also, I
have
> to manually update my .inx file every time I make an interface change.
I
> did have problems booting too as windows seemed to have trouble with
the
> boot device with the new pnp id. That may have been to do with my
> signing issues though.
>

I just tried implementing that idea again, with slightly disasterous
results. This time the network driver unloads, but windows fails to
reload it again, so I’m left with no network at all. This will never do!

I am keeping the same service name and .sys name through the upgrade, is
that going to cause problems? I changed the pnp id to xen\vif_v1 instead
of xen\vif for this update, but the driver name remains xennet.sys and
the service remains xennet. Do I need to change those?

Thanks

James


NTDEV is sponsored by OSR

For our schedule of WDF, WDM, debugging and other seminars visit:
http://www.osr.com/seminars

To unsubscribe, visit the List Server section of OSR Online at http://www.osronline.com/page.cfm?name=ListServer

>

My memory is a bit fuzzy on this point as it has been awhile, but
doesn’t
changing the hwid invalidate all the users network configuration in
the guest
when a completely new hardware devnode is materialized?

Ah yes. That was the reason why I gave up on that approach originally.
I can’t believe I forgot!!!

Thankyou for the reminder!

James

“James Harper” wrote in message
news:xxxxx@ntdev…
…,
> The fact that no one has piped up with “to prevent your driver
> unloading, do ” also suggests to me that it can’t be done.
> Probably to make sure that (like I was hoping to) nobody takes the easy
> (but incorrect) path.

But you nevertheless managed to take another hard path :frowning:
- changed the hw ids. Skywind is right (as usual), this invalidates
the network config - because many protocol settings are keyed with
the instance id of the netcard.
Perhaps it could be done with preserving the hw ids.
Also, if all new files are copied to the guest beforehand,
update can complete even without network.

Regards,
– pa

Of course, users may not like that very much. It makes upgrading a lot of VMs very painful.

(Some apps store config on a per-interface basis; IIRC, RRAS does this for firewall config, and losing that is no fun.)

  • S

-----Original Message-----
From: Pavel A.
Sent: Friday, May 15, 2009 04:29
To: Windows System Software Devs Interest List
Subject: Re:[ntdev] preventing driver unload

“James Harper” wrote in message
news:xxxxx@ntdev…
…,
> The fact that no one has piped up with “to prevent your driver
> unloading, do ” also suggests to me that it can’t be done.
> Probably to make sure that (like I was hoping to) nobody takes the easy
> (but incorrect) path.

But you nevertheless managed to take another hard path :frowning:
- changed the hw ids. Skywind is right (as usual), this invalidates
the network config - because many protocol settings are keyed with
the instance id of the netcard.
Perhaps it could be done with preserving the hw ids.
Also, if all new files are copied to the guest beforehand,
update can complete even without network.

Regards,
– pa


NTDEV is sponsored by OSR

For our schedule of WDF, WDM, debugging and other seminars visit:
http://www.osr.com/seminars

To unsubscribe, visit the List Server section of OSR Online at http://www.osronline.com/page.cfm?name=ListServer

> So I want to make all the drivers un-unloadable. Any suggestions as to how I might do this?

Just don’t register DrvUnload() in DRIVER_OBJECT if you want your driver to be unloadable, and that’s it…

What is windows behaviour on upgrade then? I would have thought it would be: .

Shut down devices for v1 driver .
Unload v1 driver .
Load v2 driver .
Try and start v2 devices

Now consider what happens if there are some outstanding references to v1 driver or to any of devices it had created - although DriverUnload() will get invoked (which means that driver module is, for the practical purposes, becomes unusable because it has already done all necessary cleanup), image itself , as well as DRIVER_OBJECT, will stay resident in RAM until all outstanding references are gone…

Anton Bassov

>

> So I want to make all the drivers un-unloadable. Any suggestions as
to how I
might do this?

Just don’t register DrvUnload() in DRIVER_OBJECT if you want your
driver to be
unloadable, and that’s it…

I am not registering DrvUnload() and the driver still gets unloaded. The
driver in question is an NDIS driver (which probably handles the
unloading itself), although I also had a filter that would not unload.

> What is windows behaviour on upgrade then? I would have thought it
would
be: .

> Shut down devices for v1 driver .
> Unload v1 driver .
> Load v2 driver .
> Try and start v2 devices

Now consider what happens if there are some outstanding references to
v1
driver or to any of devices it had created - although DriverUnload()
will get
invoked (which means that driver module is, for the practical
purposes,
becomes unusable because it has already done all necessary cleanup),
image
itself , as well as DRIVER_OBJECT, will stay resident in RAM until all
outstanding references are gone…

I see.

Thanks

James

A NSIS miniport does now own its driver context, but NDIS.SYS. It changes
all the pointers to point to its internal routines. Unloading is via direct
calls from NDIS to the miniport. There are two basic ones: Shutdown and
Halt. Not obeying those calls should be a DTM failure.

“James Harper” wrote in message
news:xxxxx@ntdev…
>
> > So I want to make all the drivers un-unloadable. Any suggestions as
to how I
> might do this?
>
> Just don’t register DrvUnload() in DRIVER_OBJECT if you want your
driver to be
> unloadable, and that’s it…
>

I am not registering DrvUnload() and the driver still gets unloaded. The
driver in question is an NDIS driver (which probably handles the
unloading itself), although I also had a filter that would not unload.

> > What is windows behaviour on upgrade then? I would have thought it
would
> be: .
>
> > Shut down devices for v1 driver .
> > Unload v1 driver .
> > Load v2 driver .
> > Try and start v2 devices
>
> Now consider what happens if there are some outstanding references to
v1
> driver or to any of devices it had created - although DriverUnload()
will get
> invoked (which means that driver module is, for the practical
purposes,
> becomes unusable because it has already done all necessary cleanup),
image
> itself , as well as DRIVER_OBJECT, will stay resident in RAM until all
> outstanding references are gone…
>

I see.

Thanks

James

> The driver in question is an NDIS driver

This changes everything - NDIS miniport driver is not supposed to be un-unloadable, which automatically implies that the answer to your original question is supposed to be negative by definition. Furthermore, it is
not supposed to communicate with the OS by any means other than NDIS library - IIRC, your NIC’s corresponding DEVICE_OBJECT that is known to the IO Manager is created by NDIS library using NDIS.SYS’s, rather than your driver’s, DRIVER_OBJECT. If you want to access your module from some component other than NDIS you have to create a standalone DO with NdisMRegisterDevice()…

Anton Bassov

>

> The driver in question is an NDIS driver

This changes everything - NDIS miniport driver is not supposed to be
un-
unloadable, which automatically implies that the answer to your
original
question is supposed to be negative by definition. Furthermore, it is
not supposed to communicate with the OS by any means other than NDIS
library -
IIRC, your NIC’s corresponding DEVICE_OBJECT that is known to the IO
Manager
is created by NDIS library using NDIS.SYS’s, rather than your
driver’s,
DRIVER_OBJECT. If you want to access your module from some component
other
than NDIS you have to create a standalone DO with
NdisMRegisterDevice()…

Hmmmm… well in that case maybe I have misunderstood what is going on
then.

The ndis driver gets some information from my bus driver. In particular,
there is no hardware interrupt, so it provides a callback routine to the
bus driver so the bus driver can tell it when there is work for it to do
(much as I expect a USB based ndis driver would, as each USB device also
doesn’t get its own interrupt).

I recently changed the api of the bus<->fdo interface, and it’s not
backwards compatible. The new fdo version will detect that it is
connected to an old bus driver version and fail to load, but it still
leaves you with no network when you upgrade until you reboot.

So before upgrade I have the following:
xenpci (v1) assigned to a virtual pci device
xenvbd (v1) scsiport driver whos fdo is enumerated by xenpci
xennet (v1) ndis miniport driver whos fdo is enumerated by xenpci
(possibly more xennet and xenvbd instances)

When I try and upgrade, xenpci cannot be upgraded on-the-fly because it
is in the paging path, ditto for xenvbd. Windows tries to upgrade xennet
but can’t load the new version and so just leaves the system with no
network driver. Upgrades where the api hasn’t changed are fine, windows
stops the v1 instance, loads the v2 driver, and starts a v2 instance.

Now I had assumed that what happened was that all the xennet devices
were being stopped, and then the xennet(v1) driver itself was unloaded
from the system, and then the xennet(v2) driver was loaded in its place.
But based on what you are saying, both xennet(v1) and xennet(v2) drivers
are in memory at the same time with the (v1) driver not responsible for
any devices anymore.

What I was hoping was that windows would stop my network interfaces, try
to unload the driver but fail (because I had prevented unload somehow
which apparently isn’t possible) and then just re-start the interfaces
with the old driver.

Another way to solve this would be for my driver to be able to tell the
difference between an ndis miniport device being stopped because it was
about to be upgraded (in which case I’d not allow it to stop if I could)
or the device being stopped because it was being ‘unplugged’ from the
system or simply disabled (in which case I’d allow it). There is no such
way to tell the difference though, and given that my requirement is a
bit of a corner case I didn’t really expect that there would be.

Thanks

James


Furthermore, it is not supposed to communicate with the OS by any means
other than NDIS library


Nope. This went away quite some time ago. Actually, it never existed. It
was just difficult to build a single driver that could talk to all of the
O/S variants that might actually tried to load it. That and the arrival of
WHQL.

It has always been permissible in some constrained ways (less so now with
the only WDM targets being NT5 and later) to use a subset of WDM mechanisms
and to a larger extent now some NT specific mechanisms.


If you want to access your module from some component other than NDIS you
have to create a standalone DO with NdisMRegisterDevice()…


That is only true if you want some other component in the system to ‘find
you’ (your NDIS driver). It is clearly not true if your NDIS Device
(Miniport Device Instance) is trying to find some other component - like its
PDO - as in this case.

The NDIS/WDM (or more recently NDIS/WDF) driver ‘model’ is perfectly adept
at and permitted to establish channels of communication with other entities
in the system by opening device file objects or issuing requests ‘in-stack’
without opening a device file object.

So presumably James’ driver issues IRPs to the lower device object which
eventually get into the bus driver by default and are processed as requests
to the PDO. Pretty standard stuff. The NDIS Miniport can use QI to get
an interface to do whatever it needs to do (defined by James as a feature of
the PDO). It can leave behind a registration for a ‘callback’ that serves
to notify the FDO driver (the NDIS Miniport in this case) that the PDO
driver (the child enumerator that actually owns the interrupt) thinks it has
something to do.

Seems perfectly reasonable and ‘legal’ by NDIS rules. If it were not,
there would be no NDIS USB drivers.

Cheers,
Dave Cattley

-----Original Message-----
From: xxxxx@lists.osr.com
[mailto:xxxxx@lists.osr.com] On Behalf Of
xxxxx@hotmail.com
Sent: Saturday, May 16, 2009 2:26 AM
To: Windows System Software Devs Interest List
Subject: RE:[ntdev] preventing driver unload

> The driver in question is an NDIS driver

This changes everything - NDIS miniport driver is not supposed to be
un-unloadable, which automatically implies that the answer to your original
question is supposed to be negative by definition. Furthermore, it is
not supposed to communicate with the OS by any means other than NDIS library
- IIRC, your NIC’s corresponding DEVICE_OBJECT that is known to the IO
Manager is created by NDIS library using NDIS.SYS’s, rather than your
driver’s, DRIVER_OBJECT. If you want to access your module from some
component other than NDIS you have to create a standalone DO with
NdisMRegisterDevice()…

Anton Bassov


NTDEV is sponsored by OSR

For our schedule of WDF, WDM, debugging and other seminars visit:
http://www.osr.com/seminars

To unsubscribe, visit the List Server section of OSR Online at
http://www.osronline.com/page.cfm?name=ListServer



Furthermore, it is not supposed to communicate with the OS by any means other than NDIS library



> This went away quite some time ago. Actually, it never existed. It was just difficult to build a
> single driver that could talk to all of the O/S variants that might actually tried to load it.
> That and the arrival of WHQL.

Please note that I am speaking about “not supposed to” and not about “technically impossible” - it is possible, but if you do it you will be unable to certify your driver if its version is below NDIS 6
(which, IIRC, applies to NDIS 5 drivers under Vista as well)…


If you want to access your module from some component other than NDIS you have to create a standalone DO with NdisMRegisterDevice()…



> That is only true if you want some other component in the system to ‘find you’ (your NDIS driver).
> It is clearly not true if your NDIS Device (Miniport Device Instance) is trying to find some
> other component - like its PDO - as in this case.

Well, strictly speaking, if you just want to find your PDO you can simply cast your miniport handle to
NDIS_MINIPORT_BLOCK structure that is declared in ndis.h. What you are going to do with it is already a different story. More on it below…

> So presumably James’ driver issues IRPs to the lower device object which eventually get into
> the bus driver by default and are processed as requests to the PDO. Pretty standard stuff.

In such case one should rather do it as a virtual miniport that interfaces a target NIC FDO that is handled by a WDM driver to NDIS. In such case you will be able to send IRPs to your target FDO on your miniport’s lower edge without any problem, i.e. do thing more or less the way NDIS USB drivers do, and your FDO will be able to deal with its PDO without a problem eeither. However, as long as your communications with a target PDO rely upon NDIS library, directly accessing bus driver from miniport one may result in some “misunderstanding” with NDIS…

Anton Bassov


Well, strictly speaking, if you just want to find your PDO you can simply
cast your miniport handle to
NDIS_MINIPORT_BLOCK structure that is declared in ndis.h.

For the record, the support way of getting the PDO in a NDIS/WDM or NDIS/WDF
miniport is to call NdisMGetDeviceProperty().

One surely does not have to resort to casting things to NDIS_MINIPORT_BLOCK
on any platform supporting NDIS 5.x (and later).

-Dave

Dave is right as always. (Or errors in his posts are not observable to me).

Don’t mess with NDIS_MINIPORT_BLOCK for purpose other than debugging. Just compare ddk defs with the structure shown in kd, one will see.

Calvin Guan
Broadcom Corp.
Connecting Everything(r)

— On Sat, 5/16/09, David R. Cattley wrote:

> From: David R. Cattley
> Subject: RE: [ntdev] preventing driver unload
> To: “Windows System Software Devs Interest List”
> Date: Saturday, May 16, 2009, 3:14 PM
>
> Well, strictly speaking, if you just want to find your PDO
> you can simply
> cast your miniport handle to
> NDIS_MINIPORT_BLOCK structure that is declared in ndis.h.
>
>
> For the record, the support way of getting the PDO in a
> NDIS/WDM or NDIS/WDF
> miniport is to call
> NdisMGetDeviceProperty().???
>
> One surely does not have to resort to casting things to
> NDIS_MINIPORT_BLOCK
> on any platform supporting NDIS 5.x (and later).
>
> -Dave
>
>
> —
> NTDEV is sponsored by OSR
>
> For our schedule of WDF, WDM, debugging and other seminars
> visit:
> http://www.osr.com/seminars
>
> To unsubscribe, visit the List Server section of OSR Online
> at http://www.osronline.com/page.cfm?name=ListServer
>