IAT patching

February 08, 2009

iat_patch.h: "This set of functions are designed to intercept functions for a specific DLL imported from another DLL." It's used in a couple of places but only when you're desparate, because this sort of stuff is inherently fragile. Off the top of my head, I know of:

  1. The Omnibox does some patching of the rich edit control for painting reasons: to reduce flicker, and to make it so the higlhight has symmetric whitespace on the top and the bottom. You might reasonably call that obsessive but part of the point of Chromium was to get the little UI we do have right.

  2. That header mentions patching crypt32.dll. I believe it's to get at some internal SSL cert data that the Windows APIs don't provide. I seem to recall some other patching in the winsock area but grepping the code now indicates it's all gone.

  3. Plugins. Plugins are not happy to run out of process, and the gnarly plugin code is filled with scary patches to make plugins still work when ran in this way. Here's an example of the sort of thing that comes up:

    // Windowless plugins can set cursors by calling the SetCursor API. This
    // works because the thread inputs of the browser UI thread and the plugin
    // thread are attached. We intercept the SetCursor API for windowless plugins
    // and remember the cursor being set. This is shipped over to the browser
    // in the HandleEvent call, which ensures that the cursor does not change
    // when a windowless plugin instance changes the cursor in a background tab.
    

    That is, the plugin thinks it's running in-process and that it can change the mouse cursor at will; but since it's not, we catch its calls to the cursor-setting API and proxy the cursor data over to the browser process, which controls the actual cursor.

As you might imagine this stuff is really easy to get wrong. r8613 attempts to fix a crash found in the destructor of the IAT patcher, that is, when it's unpatching the code. Our coding style disallows static constructors for exactly reasons like these — you can't be certain when the destructors run, and sometimes they're at the wrong times — but sometimes people think it shouldn't matter for their particular code (or they get lazy) and some statics slip past code review.

PS: A little side note. The homogeneity of Windows is here as elsewhere a blessing and a curse. I pity the people trying to push Windows forward with apps doing crazy stuff like I've just described above; on the other hand, I also expect we'll be unable to play the same sorts of tricks on heterogeneous systems like Linux. Maybe that means we'll get more flickery controls or plugin cursors won't work. All considered I prefer the latter world, because in theory I can contribute patches back upstream (at least for the controls — there's no fixing Flash). But in practice the time delay of a patch going upstream and it percolating back out to released distributions is long enough to mean you can't rely on it, which means the degraded experience is more inevitable. That seems a bit tragic too.