Some call it context, others call it reference data, but whatever it is, it’s yours


Different functions call it different things. RegisterWaitForSingleObject calls it Context. SetWindowSubclass calls it reference data. EnumWindows calls it lParam. CreateThread just calls it a parameter! But whatever its name is, it means the same thing: It's a value the function doesn't care about. All the function does is hand that value back to you. What the value means is up to you.

What if you need to pass more context than a single pointer? What if you want to pass, say, two pointers? Then put the two pointers in a structure and pass a pointer to that structure. When you do this, you introduce lifetime issues, so make sure you have a plan for deciding who is responsible for freeing the memory when it is no longer needed.

"Why isn't this documented in MSDN? Otherwise, people who call CreateThread won't know that the parameter needs to be a pointer to this structure and that the thread procedure needs to free the memory."

It's not documented in MSDN because MSDN doesn't care. This is entirely a convention within your program. It's your responsibility to ensure that the code that calls CreateThread and the thread procedure agree on what the thread parameter means and how it should be managed.

Comments (24)
  1. Dave says:

    This is useful advice. It may seem obvious to you but it would be helpful to have MSDN add a sentence or two (they could be your sentences above) to explain this very issue. You say this is common to many API calls? Okay, then, have them all link to a single page explaining the issue.

    I know this can happen when Microsoft cares enough about something, because it was done for security issues in API calls a couple of years ago. You could make the “it’s obvious to a reasonably competent programmer” argument there too, but it was documented for the unreasonably incompetent ones too. :)

    [My sentences above would be considered woefully inadequate for MSDN. “Make sure you have a plan for deciding who is responsible for freeing the memory”? People would expect MSDN to list all the possible plans and compare their pros and cons. You have to decide where MSDN ends and a book on computer programming begins, and I think “working out how to put together the building blocks into a complicated program” falls on the book side of the line. -Raymond]
  2. You’ll see this being used in a lot of C++ code. For example:

       EnumWindows(StaticEnumWindowsProc, (LPARAM)this);

       // …

    BOOL CALLBACK Foo::StaticEnumWindowsProc(HWND hWnd, LPARAM lParam)

    {

       return ((Foo *)lParam)->EnumWindowsProc(hWnd);

    }

    I believe that the C++ spec says that you shouldn’t rely on static member functions being callable as if they were C functions, but it works fine in Microsoft C++.

    Any comments about this from you, Raymond?

    [I leave that as an exercise. -Raymond]
  3. Brian says:

    Should MSDN also have a link to the C++ standard on every page just in case programmers don’t know it yet?

    (actually, that’s probably not a bad idea)

    This is one of those basic ‘always free your mallocs’ type things that you should have learned in "Intro to C++"

  4. uber1024 says:

    This is one of those interesting posts that’s going to be immediately obvious to some and might wind up making a light bulb appear over the heads of some others.  Then there’s the third group that completely ignores it and continues to supply TheDailyWTF.com with more material.

  5. Mike Jones says:

    Raymond, can I ask a dumb off topic question…

       Is Vista built on Win32?

    Just wondering.  Thanks.

  6. CRM says:

    .Net calls it "object Tag"

  7. "Is Vista built on Win32?"

    If Raymond will indulge, a rambling, off-topic reply…

    Three years ago I had to patiently explain to people with whom I worked that Visual Studio .NET 2003 could compile C and C++ code and generate native (non-managed) code. An alarmingly large number of people assumed that the ".NET" moniker indicated that the compiler suite could not output native code — I still encounter professional developers today that hold to this notion.

    While Microsoft has wisely eliminated ".NET" from the name of the current version of VS, and it was eliminated from what is now known as Windows Server 2003, I’m noticing similar confusion regarding Vista, and if it weren’t for my experience with VS 2003 I might be optimistic that it would be cleared up in short order.

    I think a number of people thought that Vista would be built on what was once called WinFX rather than a more "traditional" API like Win32. Considering that post-Longhorn-reset, Vista was begun from the Windows Server 2003 source base, it could hardly be anything else.

    PMP

  8. Dean Harding says:

    Is Vista built on Win32?

    No, it was built on Starbucks coffee and, in some cases, San Pellegrino Limonata.

  9. Mike Dimmick says:

    Define ‘Vista’ and ‘Win32’. Windows Vista has an implementation of the Win32 API and can run Win32 programs. What bit of the system is ‘the Win32 API’? Nothing. It’s a contract between the program and the OS (libraries) that says if the program does this, the OS will do that. What is a Win32 program? It’s a program that makes use of the Win32 API.

    Very circular, isn’t it?

    The Win32 API is implemented by a lot of libraries, but primarily user32.dll, kernel32.dll and gdi32.dll. These in turn talk to the Win32 Subsystem, largely implemented in CSRSS.EXE and the WIN32K.SYS driver, for windowing and graphics functions, and to the NT Executive/Kernel (ntoskrnl.exe) using the native NT API implemented in NTDLL.DLL.

    Now, if you were to ask how various subcomponents were implemented, it would be possible to answer. There were plans to implement some components on top of what is now known as WPF, but those were scaled back. Explorer is still implemented entirely with Win32 native API calls – I don’t think there’s any managed code in there at all.

  10. Mihai says:

    The problem is that many APIs don’t have a clue about this useful pattern, forcing one to use globals: EnumCalendarInfo, EnumDateFormats, EnumDateFormats, EnumTimeFormats, EnumSystemCodePages, EnumSystemLocales. Most have a (still bad) *Ex version.

    Finally, some of them are fixed by an *ExEx version, starting with Vista (took a while), but some are still not (EnumSystemCodePages).

  11. Norman Diamond says:

    I agree with those who say that it would be helpful to add a sentence to each of these MSDN pages.  Here’s why:

    > RegisterWaitForSingleObject calls it Context.

    > SetWindowSubclass calls it reference data.

    > EnumWindows calls it lParam. CreateThread just

    > calls it a parameter!

    Experienced programmers can read an MSDN page and think, how nice it would be if this could be a pointer to a structure defined by the programmer.  Experienced plus brave programmers can figure out how to experiment, casting a (struct*) to an (LPARAM) or whatever type and then decide to rely on undocumented behaviour because there’s no other way.

    If each of these MSDN pages would say “This parameter is usually a pointer to an application-defined structure, cast to an (LPARAM)” (or whatever type) then experienced programmers would be more comfortable and new programmers would have that light bulb appear over their heads.

    [I can hear the argument now.

    “You can’t pass an integer there. MSDN says that it’s usually a pointer, so you have to declare a structure and put the integer in it, and then pass the structure by address.”

    “I’m pretty sure that passing an integer is just fine. I’ve been doing it for years.”

    “Well, then you’ve been doing it wrong for years. MSDN says that you should pass a pointer. I will not sign off on your change until you change it to pass a pointer.” -Raymond

    ]

  12. Rhomboid says:

    Have any of you bought a stepladder recently?  Have you noticed that stepladders today come with what seems like pages and pages of warning stickers listing all the stupid things you shouldn’t try to do with your new ladder lest you hurt yourself.  I think I read somewhere that a significant amount of the cost of a ladder goes towards liability insurance and litigation on the part of the manufacturer, not on actual material, manufacturing, or R&D costs.

    I mention all that because it’s kind of the same thing here with MSDN.  I think any competant programmer that is practicing his art should be able to read a page of documentation that says "this DWORD can be used by the user for any purpose" and be able to realize that they can:

    • Ignore it / not set or check its value at all
    • Use it to pass a single DWORD value

    • Use it as indirection to a struct with multiple values

    • Some other variation on this

    To do anything else amounts to slathering the stepladder with paragraphs and paragraphs of warning stickers.

  13. asdf says:

    static member functions are just regular functions except instead of being looked up in global or some namespace’s scope, they’re looked up in the class’s (for the most part). The only thing you have to worry about is mixing extern "C++" function pointers with ones that expect extern "C" ones because of possible ABI issues:

    http://everything2.com/index.pl?node_id=1347400&lastnode_id=0

    I don’t think MSVC cares but I do it the correct way anyway. There is one rule you should always follow though and that’s ***never throw an exception from that callback***.

  14. Norman Diamond says:

    I can hear the argument now.

    "You can’t pass an integer there. MSDN says

    that it’s usually a pointer

    If readers can’t distinguish between "usually" and "is required to be" then let’s just hear the arguments and laugh.  It’s still better to say it than not to say it.  Compare that to the argument about whether it’s safe to pass a pointer through an LPARAM parameter when MSDN doesn’t say so (as far as I can see).

  15. Ema says:

    About Vista.

    I think I will try not to install it till I’ll be able to play games with Wine under Ubuntu, but as die-hard Win32 developer I’m asking:

    Is Vista API a C or C++ API?

    Will WinNT api calls supported (I’m not referring to ntdll.dll exported -hidden- functions), like the Net* functions?

    Thank you. :-)

  16. Norman Diamond says:

    I wrote:

    whether it’s safe to pass a pointer through

    an LPARAM parameter when MSDN doesn’t say so

    (as far as I can see).

    Sorry.  MSDN does actually say that now for ordinary (non-CE) versions of Windows.

    Tuesday, December 19, 2006 2:40 AM by Ema

    Is Vista API a C or C++ API?

    Some Win32 APIs were added to Vista.  They are callable from C.

    Will WinNT api calls supported […] like the

    Net* functions?

    Interesting.  According to

    http://msdn2.microsoft.com/en-us/library/aa370290.aspx

    NetAccessAdd is obsolete on Windows Server 2003 and Windows XP/2000/NT but not on Longhorn Server or Vista.  In the Requirements section it says that NetAccessAdd still exists on Longhorn Server and Vista.  Maybe its obsolescence is obsolete?

  17. Ema says:

    Thanks but if I’d like to develope natively for Vista, which language should I use?

    C, C++ or freakin’ .NET?

    Or, in which language should be called exported Vista API?

    Or again, basically, in which language is this operative system written?

    I hope is C,

    Thanks in advance for your answers.

  18. Ema says:

    Yes I already know what you have written; I know what you mean about __stdcall or __cdecl about who has to clear the stack and so on…

    But my question is:

    If some years ago I had to develop in Windows, before MFC, I had to use C api.

    Then with MFC I can use both C/C++.

    Now I can use C/C++/C#.

    With Vista is there a full C api?

    If I want to access all functionalities in C, can I? Do I have to forcibly use C++? Or even C# for some components?

    Will custom MSGINA.dll be supported?

    And this si another question: in which language is the O.S. core written?

  19. Michiel says:

    Yes, with Vista you can still do C. It is even more awful than it used to be, COM-in-C is horrible. It’s easier to learn VC++ than to learn COM-in-C. However, it really doesn’t matter much. x86 CPUs need binary (now also known as native or unmanaged code) so as long as your compiler emits that, you can do the same with Vista in all languages.

  20. Ema says:

    Errhhh to be honest I thought x86 CPUs needed text files and parsed them in real time and outputted directly colors and fonts on my screen… No I’m joking pal. Do you really think that people which read this blog are so ignorant?

    So is that true that all Vista APIs will be exposed even in plain C? If it’s true this would show even in these days that the old frekin’ C is even more than alive…

    What about msgina?

    And most of all, this is for my personal interest, in which language (apart the asm base) is the OS core written? Do you know?

    Are there any vital Vista DLLs (like ntdll.dll for winnt/xp) written in C++?

    Thanks again! :-)

    Ps. I don’t know why you used "VC++" word. C++ is a language, VC++ isn’t a language. I think you referred to MS C++ COM API, isn’t it?

  21. Kwailo says:

    Ema:

    Raymond had this to say about programming languages used internally at Microsoft:

    http://blogs.msdn.com/oldnewthing/archive/2005/11/25/496955.aspx#497180

    <hearsay>

      According to my spies at Redmond, the kernel is written in C. Don’t know about the rest of the OS.

    </hearsay>

  22. Jonathan says:

    Back when Windows Server 2003 was called Windows.NET, I remember having to explain to it’s not actually written in managed code.

    And yes, most of the low-level parts of the OS (kernel, ntdll.dll, etc) are written in C. There may be some parts – even there – written in C++. Grab the public symbols and have a look!

  23. Norman Diamond says:

    Tuesday, December 19, 2006 3:45 AM by Ema

    > Thanks but if I’d like to develope natively

    > for Vista, which language should I use?

    > C, C++ or freakin’ .NET?

    C and C++ can generate either native code or .NET code.  If you want to do native programming then you use native C or native C++ and do not use .NET C++.

    > Or again, basically, in which language is

    > this operative system written?

    This is a completely different question.  The APIs specify what services the built-in functions are supposed to provide to their callers when their callers meet certain conditions.  Essentially they do not specify which language either side is written in[*].  They don’t require both sides to be written in the same language.

    [* Sometimes you have to use funny eyeglasses and read the letters P A S C A L as the word __stdcall instead of the name of a programming language.]

  24. Ema says:

    Thank you guys! :-)

Comments are closed.

Skip to main content