What are these strange values returned from GWLP_WNDPROC?

GetWindowLongPtr(hwnd, GWLP_WNDPROC) [or GetWindowLong(hwnd, GWL_WNDPROC) if you haven't yet made your code 64-bit compatible] is supposed to return the current window procedure. Why do I sometimes get wacko values?

Because sometimes "you can't handle the truth".

If the current window procedure is incompatible with the caller of GetWindowLongPtr, then the real function pointer cannot be returned since you can't call it. Instead, a "magic cookie" is returned. The sole purpose of this cookie is to be recognized by CallWindowProc so it can translate the message parameters into the format that the window procedure expects.

For example, suppose that you are running Windows XP and the window is a UNICODE window, but a component compiled as ANSI calls GetWindowLong(hwnd, GWL_WNDPROC). The raw window procedure can't be returned, because the caller is using ANSI window messages, but the window procedure expects UNICODE window messages. So instead, a magic cookie is returned. When you pass this magic cookie to CallWindowProc, it recognizes it as a "Oh, I need to convert the message from ANSI to UNICODE and then give the UNICODE message to that window procedure over there."

As another example, suppose that you are running Windows 95 and the window was created by a 32-bit component, but a 16-bit component calls GetWindowLong(hwnd, GWLP_WNDPROC). Again, the raw 32-bit window procedure can't be returned since the message needs to be converted from 16-bit to 32-bit. (And besides, a 16-bit program can't jump to a 32-bit flat address.) So instead, again, a magic cookie is returned which CallWindowProc recognizes as a "Oh, I need to convert the message from 16-bit to 32-bit and then give the converted message to that window procedure over there."

(These conversions are known as "thunks".)

So remember, the only things you can do with the values you get from GetWindowLongPtr(hwnd, GWLP_WNDPROC) are to (1) pass them to CallWindowProc, or (2) pass them back to SetWindowLongPtr(hwnd, GWLP_WNDPROC).

Comments (10)
  1. Jack Mathews says:

    A couple things:

    a) What’s the survivability of that cookie, and to what does it refer? Does the window going away invalidate the cookie? If the window procedure for a remote process’ window changes, does it call that new WNDPROC? Like, is the handle basically "process/window" or some other thing that takes you to an actual pointer to the wndproc, regardless of whether or not the wndproc is attached to the window?

    b) I’d still like to see a web browser control example that lets you capture anchor clicks on real web pages. :)

  2. Benjamin says:

    What are the chances that this mechanism is removed in a future Windows version?
    It sounds a bit ugly to be honest.

    BTW: Will Avalon really remove the message pump and do everything new? No more passing of COM-stuff through windows-messages? Or will this whole stuff stay for ever under new layers?

    This should not be as negative as it sounds, but I’d really like to know if some clean up is scheduled for some point in the future or if it really makes no sense

  3. Raymond Chen says:

    The cleanup will happen when research shows that nobody runs ANSI Win32 programs any more: When they have all been converted to UNICODE or Avalon and the old ANSI versions are so old that nobody runs them any more. Don’t hold your breath, though. Our research shows that many large companies are STILL running 16-bit Windows programs that are critical to their daily operations.

  4. Fish says:

    Can’t Microsoft abstract the old architecture away with their Virtual PC technology (or similiar). This would allow older programs to see the old API’s while allowing a cleanup of the code and progression of the new technologies?

  5. evariste says:

    So *that’s* what thunking is.

  6. Mike Dimmick says:

    To configure our brand new (bought this year) print server module (D-Link, basically a palm-sized unit that plugs into the parallel port of the printer, and has an Ethernet port for plugging into the network), you can use a web browser. But what if you don’t remember the configured IP address?

    You have to install the 16-bit application that can query at Ethernet level to find the device!

    Am I right in thinking that 64-bit Windows drops 16-bit support? IIRC, Itanium doesn’t support 16-bit code at all, and AMD64 doesn’t support Virtual 8086 mode in Long (64-bit) mode.

  7. Anonymous says:

    "16-bit Windows-based applications do not run on 64-bit Windows and must be rewritten" http://msdn.microsoft.com/library/en-us/win64/win64/general_porting_guidelines.asp?frame=true

  8. Ian Hanschen says:

    You might also mention windows created under different actctx contexts.

Comments are closed.