What do the letters W and L stand for in WPARAM and LPARAM?


Once upon a time, Windows was 16-bit. Each message could carry with it two pieces of data, called WPARAM and LPARAM. The first one was a 16-bit value (“word”), so it was called W. The second one was a 32-bit value (“long”), so it was called L.

You used the W parameter to pass things like handles and integers. You used the L parameter to pass pointers.

When Windows was converted to 32-bit, the WPARAM parameter grew to a 32-bit value as well. So even though the “W” stands for “word”, it isn’t a word any more. (And in 64-bit Windows, both parameters are 64-bit values!)

It is helpful to understand the origin of the terms. If you look at the design of window messages, you will see that if the message takes a pointer, the pointer is usually passed in the LPARAM, whereas if the message takes a handle or an integer, then it is passed in the WPARAM. (And if a message takes both, the integer goes in the WPARAM and the pointer goes in the LPARAM.)

Once you learn this, it makes remembering the parameters for window messages a little easier. Conversely, if a message breaks this rule, then it sort of makes your brain say, “No, that’s not right.”

Comments (22)
  1. Jack Mathews says:

    Why not take this opportunity to fix this in Win64 then? Or is it fixed now?

    Does WinMain still take an hPrevInstance in Win64? Why is stuff like this never cleaned from the Windows API? So that you can have less #ifdef’s in the code?

  2. Curt says:

    Thanks, Raymond, I enjoy your posts. They take me back to those halcyon days of message crackers, GPFs and UAEs. :)

    Curt

  3. James Curran says:

    Jeff,
    Actually, I think it’s so *you* can have fewer #ifdef’s in *your* code. Many developers targetted both win3.1 & Win32 with a single source base for years. I expect the parellel development for Win32 & win64 to go on even longer.

  4. James Curran says:

    Jeff,
    Actually, I think it’s so *you* can have fewer #ifdef’s in *your* code. Many developers targetted both win3.1 & Win32 with a single source base for years. I expect the parellel development for Win32 & win64 to go on even longer.

  5. James Curran says:

    Jeff,
    Actually, I think it’s so *you* can have fewer #ifdef’s in *your* code. Many developers targetted both win3.1 & Win32 with a single source base for years. I expect the parellel development for Win32 & win64 to go on even longer.

  6. Ivan Towlson says:

    Jeff, I think binary compatibility might be an issue as well. Native-code binaries tend to break if the number or size of function arguments etc. change, because the assumptions about the number of bytes on the stack or the offsets of structure members are baked into the binary. And it’s a pain to have to ship different binaries for different platforms.

    I think this is why as the Win32 API evolved they’ve moved towards using structures and versioning these using a size indicator as the first element (the cbSize member we see on so many API structs). This way the API can gain new "arguments" (struct members) but detect the caller’s expectations and structure layout in case it’s not been built against the latest and greatest header files.

  7. Adam Wimsatt says:

    Great info. Do you know of an example of a message that breaks this rule?

  8. evariste says:

    Jeff, unlike those two I know that your name is Jack, so while I have no useful information to offer you, Jack, gosh, aren’t you grateful at least I know your name?
    :P

  9. Eric Wilson says:

    This is one of THE classic example of why Hungarian notation is a bad idea in any code that you think will survive long term.

  10. Eric Wilson says:

    This is one of THE classic example of why Hungarian notation is a bad idea in any code that you think will survive long term.

  11. Here’s a mind-boggling question: why does every computer made (from 8086 up to the Intel/AMD processors of today) beep continuously when you hold down all six of the shift, alt and ctrl keys. :)

  12. Insanity says:

    I think the beep to which you’re referring is the heard only when muppets hold down keys (or sit on their keyboard).

  13. Jack, Not Jeff, Mathews says:

    James: Yes, but that lack of #ifdefs pays a price. You have all of this built in crap that never works its way out of the API. You have ShellExecute and ShellExecuteEx, you have CreateFont and CreateFontIndirect. You have WinMain. You have pointers declared with NEAR in them still in the .h files.

    If they want to maintain compatibility, then give us a migration .lib (or .cpp’s and .h’s) rather than keeping all of this crap in the Windows DLLs. Clean things up.

    Namespace things so that functions begin with their subsystem (like the Reg* functions!). Make the UNICODE functions default and ANSI ones end in A so that we don’t have to have functions like GetComputerName #defined out in our code differently if we include windows.h or not.

    Ok, I’ll take some happy pills and chill out now.

  14. Jesse Ezell says:

    The Win32 API is broken beyond repair, that’s why we are getting WinFX instead of a new Win32 API. Things are not only getting "cleaned up," they are being written correctly from the ground up.

  15. Jesse Ezell says:

    The Win32 API is broken beyond repair, that’s why we are getting WinFX instead of a new Win32 API. Things are not only getting "cleaned up," they are being written correctly from the ground up.

  16. tekumse says:

    Matt, mine beeps on both control keys and any one shift.

  17. "So even though the "W" stands for "word", it isn’t a word any more."

    I think it is. As far as I remember, word relates to the standard size used for data on a machine, perhaps the register size. For example, DEC TOPS-20 machines used to (still?) have 36-bit words (I seem to remember some awkward transformations for downloading files from these machines – didn’t simtel used to run on TOPS-20 or something when it was at wsmr? Always used to think it was cool connecting up to a computer 1000’s of miles away on a missile range but I digress). On a 32-bit system, the word size is 32-bit so it WORD is a 32-bit value.

    c.f. http://info.astrian.net/jargon/terms/n/nybble.html

  18. Perry Lorier says:

    Matt Mastracci: The beep is because the way the keyboard is scanned. It’s layed out in some kind of grid with the keys connecting the rows and the columns together. Power is applied to each column sequentially and then you look at which row has power coming out of it. From the intersection of the column and the row together you can figure out which key was pressed. However there is one flaw, if you press three keys in a "triangle" then the current can flow down the column, across where you pressed one of the keys, then down at the next key then across again. (Hmm, diagram here would be useful). When this happens the computer starts reading "ghost" keys. The computer can detect this condition and "beeps" at you slowly to let you know that it can’t reliably tell which keys are being pressed. This used to be an excellent way of telling if your computer hasn’t crashed, since if it had crashed (And taken out the keyboard handler) then it wouldn’t beep (since t wasn’t processing interrupts from the keyboard anymore)

  19. Claw says:

    Perry: Actually that’s not true… at least not for modern PC keyboards. The beep is caused when the keyboard buffer in the BIOS is full. If you hold down too many keys at the same time, signals from the keyboard fill up the buffer faster than the OS handles them, causing the BIOS to make your computer beep. You can also see this happen when your computer crashes and locks up… if you keep typing on your computer while it is frozen, it will eventually beep at you when you have filled the keyboard buffer (since the OS is frozen and doesn’t handle it).

  20. Perry Lorier says:

    At least under Dos, the beep you got from the bios keyboard buffer filling up was quite different, holding down all the shift keys gave you a beep with very long pauses between them. Under Windows 3.1 when the message buffer filled up the computer would beep at you too.

  21. Raymond Chen says:

    Once a function is exported from a specific DLL you can’t move it. If you did, then you would break all the old programs that expected to see it in the old DLL. A migration DLL doesn’t help because it requires everybody with an old program recompiled it with the migration DLL — good luck trying to get Borland (for example) to recompile Sidekick 2.0 for Windows, or that ActiveX control you bought in 1998 from a company that is no longer in business.

    Moving functions into namespaces has the same problem – but worse: Not all languages support namespaces. (C for example doesn’t.)

  22. Nikola Petrovic says:

    Ive been trying to understand how to increase the buffert in the BIOS for the keyboard so that more keys can be pressed at the same time.

    Is there any way to do this?

Comments are closed.