Rebooting a system safely in the presence of RunOnce keys?

I have a weird scenario that I’m not sure how to work around.

It starts when a user upgrades our drivers and whatnot for a system that has
our card in it. We then reboot the system. When our new drivers come up,
they may notice that a firmware or FPGA upgrade might need to be done to the
hardware (depending on the rev of the hardware and previous upgrades that
may have been done), so we will upgrade that. However, we then need to do
another reboot of the system to get the hardware / drivers going again, so
we call InitiateSystemShutdown. However, in the meantime, the user may have
logged in manually or due to AutoAdminLogon, so the system may be logged in
and processing RunOnce keys and so on. A few times, we’ve seen that the
system then gets a bit messed up due to us rebooting the system in the
middle of some RunOnce process (such as an IE upgrade).

So, how do we avoid rebooting the system while the system is doing “stuff”?
(The GUI avoids this because the desktop is not created until all of the
RunOnce keys have been created, so the user can’t request a shutdown that
way, although Ctl-Alt-Del works, so I guess they could cause the same
trouble manually.)

Unfortunately, our service doesn’t start early enough to stop an auto-login,
and it’s one of the earliest services in the system, so I think that may not
be possible to do.

I did discover that RunOnce processes are executed serially (the second one
does not start until the first has finished), and they are removed as the
processes are started, so I considered monitoring all of the various RunOnce
and RunOnceEx values/keys and waiting until they were empty. But then what
would happen if some RunOnce adds more RunOnce keys? (Is that possible?)

Another idea was to remove any auto-logon info prior to the first boot, and
then restore it when we think it’s safe to do so, but it seems that that
info is only examined on a reboot, or could we somehow force the system to
auto-logon if necessary? (Or is there even a way to programmatically log in
a user from a service?)

I couldn’t come up with a clean/obvious solution to this, and I figured that
if anyone else has run into this, it would be the people on this list…

Suggestions? Am I just missing something obvious?

(Thanks!)

My preference would be for the second reboot to require UI input to
proceed; i.e. a RunOnce entry that pops up a short wizard that simply
indicates to the user that another reboot is necessary. It’s rude to
just fire the second reboot with no warning. If you build your
installation/upgrade around MSI this sort of thing is easy to do.

Taed Wynnell wrote:

I have a weird scenario that I’m not sure how to work around.

It starts when a user upgrades our drivers and whatnot for a system that has
our card in it. We then reboot the system. When our new drivers come up,
they may notice that a firmware or FPGA upgrade might need to be done to the
hardware (depending on the rev of the hardware and previous upgrades that
may have been done), so we will upgrade that. However, we then need to do
another reboot of the system to get the hardware / drivers going again, so
we call InitiateSystemShutdown. However, in the meantime, the user may have
logged in manually or due to AutoAdminLogon, so the system may be logged in
and processing RunOnce keys and so on. A few times, we’ve seen that the
system then gets a bit messed up due to us rebooting the system in the
middle of some RunOnce process (such as an IE upgrade).

So, how do we avoid rebooting the system while the system is doing “stuff”?
(The GUI avoids this because the desktop is not created until all of the
RunOnce keys have been created, so the user can’t request a shutdown that
way, although Ctl-Alt-Del works, so I guess they could cause the same
trouble manually.)

Unfortunately, our service doesn’t start early enough to stop an auto-login,
and it’s one of the earliest services in the system, so I think that may not
be possible to do.

I did discover that RunOnce processes are executed serially (the second one
does not start until the first has finished), and they are removed as the
processes are started, so I considered monitoring all of the various RunOnce
and RunOnceEx values/keys and waiting until they were empty. But then what
would happen if some RunOnce adds more RunOnce keys? (Is that possible?)

Another idea was to remove any auto-logon info prior to the first boot, and
then restore it when we think it’s safe to do so, but it seems that that
info is only examined on a reboot, or could we somehow force the system to
auto-logon if necessary? (Or is there even a way to programmatically log in
a user from a service?)

I couldn’t come up with a clean/obvious solution to this, and I figured that
if anyone else has run into this, it would be the people on this list…

Suggestions? Am I just missing something obvious?

(Thanks!)


Nick Ryan (MVP for DDK)

What is the hardware? I hope not USB one?

Maxim Shatskih, Windows DDK MVP
StorageCraft Corporation
xxxxx@storagecraft.com
http://www.storagecraft.com

----- Original Message -----
From: “Taed Wynnell”
To: “Windows System Software Devs Interest List”
Sent: Thursday, December 04, 2003 3:10 AM
Subject: [ntdev] Rebooting a system safely in the presence of RunOnce keys?

> I have a weird scenario that I’m not sure how to work around.
>
> It starts when a user upgrades our drivers and whatnot for a system that has
> our card in it. We then reboot the system. When our new drivers come up,
> they may notice that a firmware or FPGA upgrade might need to be done to the
> hardware (depending on the rev of the hardware and previous upgrades that
> may have been done), so we will upgrade that. However, we then need to do
> another reboot of the system to get the hardware / drivers going again, so
> we call InitiateSystemShutdown. However, in the meantime, the user may have
> logged in manually or due to AutoAdminLogon, so the system may be logged in
> and processing RunOnce keys and so on. A few times, we’ve seen that the
> system then gets a bit messed up due to us rebooting the system in the
> middle of some RunOnce process (such as an IE upgrade).
>
> So, how do we avoid rebooting the system while the system is doing “stuff”?
> (The GUI avoids this because the desktop is not created until all of the
> RunOnce keys have been created, so the user can’t request a shutdown that
> way, although Ctl-Alt-Del works, so I guess they could cause the same
> trouble manually.)
>
> Unfortunately, our service doesn’t start early enough to stop an auto-login,
> and it’s one of the earliest services in the system, so I think that may not
> be possible to do.
>
> I did discover that RunOnce processes are executed serially (the second one
> does not start until the first has finished), and they are removed as the
> processes are started, so I considered monitoring all of the various RunOnce
> and RunOnceEx values/keys and waiting until they were empty. But then what
> would happen if some RunOnce adds more RunOnce keys? (Is that possible?)
>
> Another idea was to remove any auto-logon info prior to the first boot, and
> then restore it when we think it’s safe to do so, but it seems that that
> info is only examined on a reboot, or could we somehow force the system to
> auto-logon if necessary? (Or is there even a way to programmatically log in
> a user from a service?)
>
> I couldn’t come up with a clean/obvious solution to this, and I figured that
> if anyone else has run into this, it would be the people on this list…
>
> Suggestions? Am I just missing something obvious?
>
> (Thanks!)
>
>
> —
> Questions? First check the Kernel Driver FAQ at
http://www.osronline.com/article.cfm?id=256
>
> You are currently subscribed to ntdev as: xxxxx@storagecraft.com
> To unsubscribe send a blank email to xxxxx@lists.osr.com

> My preference would be for the second reboot to require UI input to

proceed; i.e. a RunOnce entry that pops up a short wizard that simply
indicates to the user that another reboot is necessary. It’s rude to
just fire the second reboot with no warning.

I left out an important piece of information: This is an “embedded” system
with no monitor / keyboard / mouse. It’s our box, but using an SMS-like
installation application running remotely, the owning company can update
various software on it (to thousands of machines at once). So, in that
context, our funky reboot is not “rude”, but the right thing to do.
However, we do need to figure out how to do it cleanly so that we don’t get
in the way of other software being installed at the same time.

What is the hardware? I hope not USB one?

It’s custom hardware, some of which is ISA, PCI, and custom busses.

Basically, you’re saying you want to delay login while performing your
upgrade. The most straightforward way to do this is with a Winlogon
Notification .dll that handles the ‘Logon’ event by blocking until your
service has completed its tasks. Lookup ‘Winlogon Notification Packages’
in the SDK.

Taed Wynnell wrote:

>My preference would be for the second reboot to require UI input to
>proceed; i.e. a RunOnce entry that pops up a short wizard that simply
>indicates to the user that another reboot is necessary. It’s rude to
>just fire the second reboot with no warning.

I left out an important piece of information: This is an “embedded” system
with no monitor / keyboard / mouse. It’s our box, but using an SMS-like
installation application running remotely, the owning company can update
various software on it (to thousands of machines at once). So, in that
context, our funky reboot is not “rude”, but the right thing to do.
However, we do need to figure out how to do it cleanly so that we don’t get
in the way of other software being installed at the same time.

>What is the hardware? I hope not USB one?

It’s custom hardware, some of which is ISA, PCI, and custom busses.


Nick Ryan (MVP for DDK)

Just thinking for a few seconds on this, I think I’d split this problem into
two phases: detecting the need to reboot, and then doing the reboot. This
leaves an intermediate time when the drivers are presumably non-functional
for whatever reason. However, since this is your system that should be
manageable.

I would have the driver(s) make a determination that a reboot is required
and set a flag somewhere indicating this fact. Registry key, internal flag
communicated to a system service, internal flag that will cause a unique
failure on driver open or be interrogated by an ioctl; it doesn’t much
matter.

Then, since this is your box, you presumably have stuff that auto-starts
after the login happens, and therefore after run-once. At this point I
would have an app check the reboot required flag by whatever method is
convenient, and request the reboot itself.

This might add a minute or so to the time required for this reboot, and
therefore to the time your system is effectively DOA. Depending on what
your system does this may or may not be acceptable. However, since you
mentioned that this situation happens at upgrade times, I am assuming that
this is during scheduled maint, and you can deal with the extra minute or
two.

Loren

Thanks for the replies!

We ended up doing essentially what Loren Wilton suggested – we added a last
event in the RunOnce key (oddly enough, NT processes them in the order of
creation, but 2000 does it in Alphabetical order) which does essentially
nothing. The reboot service then waits for the RunOnce keys to all be
deleted. This works because the keys are run serially by the system, and
the key for each is deleted when it is run (if they were deleted when the
process finished, then we wouldn’t have needed a last key).

NRyan’s suggestion (register a logon notification event) was pretty cool,
though; I didn’t know that was possible. That was probably a more robust
solution (and the way I wanted to do it), but as a group we felt more comfy
with the first.

Thanks!

Note that the Run keys are executed after the RunOnce keys, so you may
be attempting to reboot while Run apps are still being launched.
Winlogon notification packages are reliable, but the caveat is that they
aren’t supported under NT4. Tough problem, isn’t it?

Taed Wynnell wrote:

Thanks for the replies!

We ended up doing essentially what Loren Wilton suggested – we added a last
event in the RunOnce key (oddly enough, NT processes them in the order of
creation, but 2000 does it in Alphabetical order) which does essentially
nothing. The reboot service then waits for the RunOnce keys to all be
deleted. This works because the keys are run serially by the system, and
the key for each is deleted when it is run (if they were deleted when the
process finished, then we wouldn’t have needed a last key).

NRyan’s suggestion (register a logon notification event) was pretty cool,
though; I didn’t know that was possible. That was probably a more robust
solution (and the way I wanted to do it), but as a group we felt more comfy
with the first.

Thanks!


Nick Ryan (MVP for DDK)