Just Let It Flow

April 8, 2014

DefRawInputProc-rastinating Away

Filed under: Windows — adeyblue @ 2:36 am

The Raw Input function are, shall we say, tersely documented. There’s a single piece of sample code, dubious as is it, and generally enough description of the six or so main functions to grasp what they do and why you need them. Register a device, wait for messages, get the input data, process it, a pattern Windows has employed many times. But what about the seventh function? It’s a bit of a joker.

The MSDN page for DefRawInputProc states:

Calls the default raw input procedure to provide default processing for any raw input messages that an application does not process. This function ensures that every message is processed.

It certainly sounds like an important part of any WM_INPUT handling code you should happen to be writing. After all, if you don’t process the input messages, it could lead to a backlog of unprocessed data that may have a detrimental effect on application or system input. There’s precedent, if you’ve ever tried writing a window procedure and missed out the DefWindowProc, you’ll know the window starts behaving unexpectedly.

But hang on a second, in the Using Raw Inputsample code mentioned earlier, there’s a comment above the DefRawInputProc invocation like so:

    // to clean the buffer
    DefRawInputProc(paRawInput, nInput, sizeof(RAWINPUTHEADER));

Hmm, I can’t think of any interpretation of ‘cleaning the buffer’ that arrives at ‘processing unprocessed messages’. Then again, the sample was (presumably) written by Microsoft so maybe it does clean a buffer as well as or instead of the original claims.

Given these two different descriptions of what the function does, there’s only one thing to be done to settle what it actually does. Taking a peek under the hood of Windows 8’s user32.dll reveals:

_DefRawInputProc@12 proc near
 
arg_8           = dword ptr  10h
 
                mov     edi, edi
                push    ebp
                mov     ebp, esp
                xor     eax, eax
                cmp     [ebp+arg_8], 16
                setz    al
                dec     eax
                pop     ebp
                retn    0Ch
_DefRawInputProc@12 endp

Is that it? What amounts to nineteen bytes of assembly doesn’t seem much for all these jobs it supposedly does. That’s because it doesn’t do them. No processing of messages of any kind, no cleaning of the buffer for any definition of that phrase, no nothing. All the assembly shows is that the function compares the last parameter ‘cbSizeHeader’ to 16 (the size of a RAWINPUTHEADER struct) and returns 0 if they match, or -1 if they don’t. That’s all. At current time of writing, the entire function is more than 11 times shorter than its MSDN description!

OK, before we start baying for the head of the documentation writer consider that we’re now at Windows 8.1 and this function started life in XP. Maybe it’s just a historical leftover. Maybe it used to do something in an earlier incarnation, and was shortened to it’s current length due to improved implementation elsewhere or something. After all, the MSDN sample code has a commented out parameter to GetRawInputBuffer so it’s not too far fetched that these API’s were changing as the documentation of them was being written.

Let’s go back in time and check. Set the time machine to 12th October 2000, for that’s the date of the earliest build of Windows XP that has raw input support. This is way back when it was known as Windows Whistler, when its’ first beta was being released to testers, and when User32.dll still identified itself as being from Windows 2000.

The youngest incarnation of DefRawInputProc, reveal yourself:

DefRawInputProc proc near
 
arg_8           = dword ptr  0Ch
 
                xor     eax, eax
                cmp     [esp+arg_8], 12
                setz    al
                dec     eax
                retn    0Ch
DefRawInputProc endp

Shock of shocks, the function was even smaller back then. Mainly due to the absence of the 5 byte hotpatch padding, but smaller nonetheless. And look at that, it did exactly the same thing it still does now, except the size it compares against was smaller by 4.

So what does DefRawInputProc do? Nothing but procrastinate. It didn’t do any work when it first came about, it’s doing none now, and probably won’t ever. Microsoft’s intention behind calling this function might have been to plug some sort of processing in at a later date, without needing people to rewrite their code. They might’ve meant to implement it proper in a future build but never got round to it, they might’ve meant a lot of things. What it is though, is a waste of time.

Powered by WordPress