OSR Dev Blog

MmGetSystemRoutineAddress IS BROKEN!?
(By: OSR Staff | Published: 31-May-07| Modified: 05-Jun-07)

Updated 5 June 2007:

It seems that I missed a story recently.  M'ijo Peter was reading NTDEV recently, when driver expert Bill McKenzie asked a simple question:

Am I crazy, or is MmGetSystemRoutineAddress supposed to return NULL when it does not find the requested system routine name...? On XP SP2, looking for CmRegisterCallbackEx using MmGetSystemRoutineAddress it blue screens everytime.

Bill even posted a nice, simple, example and a detailed crash dump.

I know, I know... you're thinking "How can there be a bug in so fundamental a DDI as this, and not have more people know about it?"  Well, as the members of NTDEV pointed out, it seems that this has been a well-known problem for quite a while.  Konstatin Manurin posted an analysis of the problem back in November of 2006 (see http://www.osronline.com/showThread.cfm?link=101536).

The boys up in Redmond (thank you DoronH and RobertKj) have confirmed that this is a indeed a known problem that's fixed in Vista and slated for fix in XP SP3.

OSR's PeterGV has indicated that it's also fixed in S03 SP1.

Contrary to initial guidance, MS sources have indicated that it is not safe to catch this error in a try/except block.  Apparently, catching the error with SEH can result in a lock not being properly released.  Ugh.

The latest guidance is to build-knowledge into your code as to whether the function you want to call is exported, so to check for  CmRegisterCallbackEx which was first provided on Vista, your code would look something like:

if ( RtlIsNtDdiVersionAvailable(NTDDI_LONGHORN) ) {

    //
    // This function is available...
    //
    rtnToCall =  MmGetSystemRoutineAddress (...);

} else {

    //
    // The function's not available... get a pointer to an alternative function
    //
    rtnToCall =  MmGetSystemRoutineAddress (...);

}

This technique complicated by the fact that the WDK docs don't typically say when a DDI was first implemented.

Also, given that the bug is fixed on Vista and Server 2003 SP1 and later system, you can use RtlIsNtDdiVersionAvailable and RtlIsServicePackVersionInstalled to check to see if it's safe to call MmGetSystemRoutineAddress.

A mess for all, that's for sure.

Another possible work-around (and the one we've chosen to use here at OSR) is to write your own version of MmGetSystemRoutineAddress.  Believe it or not, you can even do it with documented DDIs...  Check out the AuxKlibQueryModuleInformation (which is implemented in a static library that's only present in the Vista build environment of the WDK).

This article was printed from OSR Online http://www.osronline.com

Copyright 2017 OSR Open Systems Resources, Inc.