// ke_irql.c - software IRQL skeleton #include #include #include // Single-CPU bring-up state. When SMP arrives this becomes per-CPU state. static volatile KIRQL gCurrentIrql = PASSIVE_LEVEL; __declspec(dllexport) const char* KeIrqlName(KIRQL irql) { switch (irql) { case PASSIVE_LEVEL: return "PASSIVE_LEVEL"; case APC_LEVEL: return "APC_LEVEL"; case DISPATCH_LEVEL: return "DISPATCH_LEVEL"; case HIGH_LEVEL: return "HIGH_LEVEL"; default: if (irql >= DIRQL_BASE && irql < HIGH_LEVEL) return "DIRQL"; return "INVALID_IRQL"; } } __declspec(dllexport) KIRQL KeGetCurrentIrql(void) { return gCurrentIrql; } __declspec(dllexport) KIRQL KeRaiseIrql(KIRQL newIrql) { KIRQL oldIrql = gCurrentIrql; if (newIrql > HIGH_LEVEL) { KePanic("KeRaiseIrql: invalid target IRQL %u\n", (unsigned)newIrql); } if (newIrql < oldIrql) { KePanic("KeRaiseIrql: attempted raise from %s(%u) down to %s(%u)\n", KeIrqlName(oldIrql), (unsigned)oldIrql, KeIrqlName(newIrql), (unsigned)newIrql); } gCurrentIrql = newIrql; return oldIrql; } __declspec(dllexport) void KeLowerIrql(KIRQL oldIrql) { KIRQL currentIrql = gCurrentIrql; if (oldIrql > HIGH_LEVEL) { KePanic("KeLowerIrql: invalid target IRQL %u\n", (unsigned)oldIrql); } if (oldIrql > currentIrql) { KePanic("KeLowerIrql: attempted lower from %s(%u) up to %s(%u)\n", KeIrqlName(currentIrql), (unsigned)currentIrql, KeIrqlName(oldIrql), (unsigned)oldIrql); } gCurrentIrql = oldIrql; if (oldIrql == PASSIVE_LEVEL && currentIrql != PASSIVE_LEVEL) KiDeliverKernelApcs(); } __declspec(dllexport) void KeAssertIrql(KIRQL expected) { KIRQL currentIrql = KeGetCurrentIrql(); if (currentIrql != expected) { KePanic("IRQL assertion failed: expected %s(%u), current %s(%u)\n", KeIrqlName(expected), (unsigned)expected, KeIrqlName(currentIrql), (unsigned)currentIrql); } } __declspec(dllexport) void KeAssertIrqlAtOrBelow(KIRQL maxIrql) { KIRQL currentIrql = KeGetCurrentIrql(); if (currentIrql > maxIrql) { KePanic("IRQL assertion failed: expected <= %s(%u), current %s(%u)\n", KeIrqlName(maxIrql), (unsigned)maxIrql, KeIrqlName(currentIrql), (unsigned)currentIrql); } } __declspec(dllexport) int KeCanWait(void) { return KeGetCurrentIrql() == PASSIVE_LEVEL; }