If DO_POWER_PAGABLE bit is set, the power manager shouldn't send power IRPs
at DISPATCH_LEVEL. I know for sure, on XP, the power manager checks this bit
and queues a workitem if you happen to call PoCallDriver at DISPATCH_LEVEL.
May be this fix is not there on Win2K and hence the crash. I never ran into
this on Win2K myself.
Recently I discussed this issue with out power management team and they
suggested me to do as follows:
1) In the AddDevice device after you attach your deviceobject to the lower
one, check it's Flags to see if the DO_POWER_INRUSH is set. If it's set then
you should set that in your device object. ( I don't know when and why would
the driver below me decide to set this bit. It seems that ACPI driver for
some weird reasons may choose to set that). If the DO_POWER_INRUSH bit is
set in the lower deviceobject then you shouldn't set DO_POWER_PAGABLE in
yours because they are exclusive.
2) If the DO_POWER_INRUSH is not set then check to see if the
DO_POWER_PAGABLE bit is set. If it's set then set that in your deviceobject.
3) Finally if the DO_POWER_PAGABLE is not set in your deviceobject, lock
all your power management code in your driver. Either this or you should
just avoid marking all the Power management routines pageable altogether to
keep it simple.
Here is a code snippet from a sample:
//
// Bit Flag Macros
//
#define SET_FLAG(Flags, Bit) ((Flags) |= (Bit))
#define CLEAR_FLAG(Flags, Bit) ((Flags) &= ~(Bit))
#define TEST_FLAG(Flags, Bit) (((Flags) & (Bit)) != 0)
//
// The DO_POWER_PAGABLE bit of a device object indicates to the
// kernel that the power-handling code of the corresponding
// driver is pageable, and so must be called at PASSIVE_LEVEL.
// Before we set it, we must check the deviceobject beneath
// us to see if the DO_POWER_INRUSH is set.
//
if (TEST_FLAG(fdoData->NextLowerDriver->Flags, DO_POWER_INRUSH)) {
//
// If we set DO_POWER_INRUSH, we shouldn't set DO_POWER_PAGABLE and
// make sure all our power-handling code is either locked or marked
// nonpageable because we can get power IRPs at DISPATCH_LEVEL.
//
SET_FLAG(deviceObject->Flags, DO_POWER_INRUSH);
} else if(TEST_FLAG(fdoData->NextLowerDriver->Flags, DO_POWER_PAGABLE)){
SET_FLAG(deviceObject->Flags, DO_POWER_PAGABLE);
}
//
// If the power pageable bit is not set, we will lock the code section
// that contains all the power handling code so that it can be safely
// called at IRQL>PASSIVE_LEVEL.
//
if(!TEST_FLAG(deviceObject->Flags, DO_POWER_PAGABLE))
{
fdoData->PowerCodeLockHandle = MmLockPagableCodeSection(
(PVOID)PciDrvDispatchPower);
}
// Don't forget to unlock the pages in Remove-Device handler.
--
-Eliyas
This posting is provided "AS IS" with no warranties, and confers no rights.
http://www.microsoft.com/whdc/hwdev/driver/kb-drv.mspx