OSRLogoOSRLogoOSRLogo x Seminar Ad

Everything Windows Driver Development

GoToHomePage xLoginx

    Thu, 14 Mar 2019     118020 members


  Online Dump Analyzer
OSR Dev Blog
The NT Insider
The Basics
File Systems
ListServer / Forum
  Express Links
  · The NT Insider Digital Edition - May-June 2016 Now Available!
  · Windows 8.1 Update: VS Express Now Supported
  · HCK Client install on Windows N versions
  · There's a WDFSTRING?
  · When CAN You Call WdfIoQueueP...ously

Loading DLLs for Graphics Drivers

So, I'm just a little old graphics person, doing the simple DDI thing of bitblt, text and paint optimizations, trying to figure out the best way to decipher one of the zillion ROP4 incantations that just came down. When, to my consternation, I find that DDI doesn’t build anymore because the 3D folks just checked something in and broke everything. One way to get around this would be to string them up by their Grouand shaded toenails. But hey, Windows NT allows for dynamic loads of code images, right? Should be doable for graphics device drivers as well, right? This way when those 3D guys make the next big "optimization" for the pomegranate stippled triangles, it won't effect my ROP4 meditations.



So, how exactly to do the load? The following code fragment will do just that (Figure 1). What we do is call EngLoadImage(…) to load the target DLL. Then, we call EngFindImageProcAddress(…) to find an entry point in the target DLL that will initialize something, like a routine vector table or some other mechanism to enjoin this loaded functionality.

Note that we store the handle to the loaded image in our PDEV so that later on we could optionally unload this image/functionality.

// include the usual suspects
#include <stddef.h>
#include <stdarg.h>
#include <limits.h>
#include <windef.h>
#include <wingdi.h>
#include <winddi.h>

typedef struct {
    HANDLE hStuff;

// local typedefs (specifically, for the loaded image entry point)
typedef BOOL (*PDLLENTRY) (PPDEV pdev);

VOID LoadStuffDebugPrint(
    PCHAR DebugMessage,

    va_list ap;
    va_start(ap, DebugMessage);
    EngDebugPrint("LoadStuff : ", DebugMessage, ap);

BOOL LoadStuff (char *pFileName, char *pEntryPointName, PPDEV pdev)
    WCHAR uDllName[128]; // driver name in unicode
    ULONG uNameSize; // size in unicode
    PDLLENTRY pEntry;        // entry point
    // translate the character string into unicode because the DDI
    // folks are all K&R C writers anyway
    EngMultiByteToUnicodeN(uDllName, (ULONG)sizeof(uDllName),uNameSize,
        pFileName, (ULONG)strlen(pFileName));

    // try and load the image
    pdev->hStuff = EngLoadImage (uDllName);
    // Bummer if we can't get it
    if (!pdev->hStuff)
        LoadStuffDebugPrint("Error loading %s\n", pFileName);
        return FALSE;
    // Find the entry point
    pEntry = (PDLLENTRY) EngFindImageProcAddress (pdev->hStuff,(LPSTR) pEntryPointName);
    // Bummer if we can't get into the image (the 3D guys were probably
    // lying to us about this entry point anyway)
    if (!pEntry)
        LoadStuffDebugPrint("Cannot find entry point %s\n",pEntryPointName);

        pdev->hStuff = NULL;
        return FALSE;
    // Got it. Invoke it.
    if (!pEntry(pdev))
        LoadStuffDebugPrint("Failure during initialization %s\n",pEntryPointName);

        pdev->hStuff = NULL;
        return FALSE;
    // we're all happy now. Let's go home.
    return TRUE;

Figure 1

Be Careful!


Note, however, that there are some of the "usual" graphics device driver restrictions:

  1. If the target is a graphics based DLL:

a.       You have the same linking restrictions, routine restrictions, stack restrictions, etc., that you have when implementing your 2D DDI DLL. Specifically, you can only link against win32k.lib and not anything else (like ntoskrnl.lib). Yes, you can still link against libcntpr.lib for some C-runtime stuff.

b.        You need to export the entry point in your target DLL, which can be easily done by inserting the following into the target DLL’s SOURCES file:


·         TARGET_TYPE in the target DLL’s SOURCES file is GDI_DRIVER

·         You need a DrvEnableDriver entry point.


  1. If the target is a non-graphics, or "standard kernel" driver:
    1. You cannot have any EngXXX routine references (e.g., you can't link against win32k.lib).
    2. You need to export the entry point in your target SYS, which can easily be done by generating a .DEF file which has the following text:

EXPORTS EntryPoint

·         TARGET_TYPE in the target DLL’s SOURCES file is EXPORT_DRIVER

·         You need a DriverEntry entry point.


  1. And the others things your mother always told you to do:

a.       Watch your stack, and now your siblings stack as well.

b.      Stay away from floating point operations (unless you're OpenGL or Direct3D or you're on an Alpha).

c.       Don’t talk to routines like KeXXX, MmXXX, IoXXX. These are for Mr. Miniport. And I know that you’re doing this already.

d.      Don't to eat too many large, perspective texture mapped, 5-light, fogged, triangles at one time.

e.       Only take as much memory as you really need. There are starving objects in non-paged pool land and they’re not all as lucky as you.


Related Articles
From Andy's Bookshelf: Loading Video Drivers, a Mystery Solved
From Andy's Bookshelf: So you Wanna Write a Video Driver
From Andy's Bookshelf: Floating Point Triage
From Andy's Bookshelf: WinDbg Extension for GDI
From Andy's Bookshelf: Video Drivers and the Registry

User Comments
Rate this article and give us feedback. Do you find anything missing? Share your opinion with the community!
Post Your Comment

Post Your Comments.
Print this article.
Email this article.
bottom nav links