Date: | December 18, 2006 / year-entry #417 |
Tags: | code |
Orig Link: | https://blogs.msdn.microsoft.com/oldnewthing/20061218-04/?p=28683 |
Comments: | 24 |
Summary: | 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... |
Different functions call it different things. 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 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 |
Comments (24)
Comments are closed. |
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. :)
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?
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++"
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.
Raymond, can I ask a dumb off topic question…
Is Vista built on Win32?
Just wondering. Thanks.
.Net calls it "object Tag"
"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
No, it was built on Starbucks coffee and, in some cases, San Pellegrino Limonata.
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.
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).
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.
“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
]
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:
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.
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***.
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).
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. :-)
I wrote:
Sorry. MSDN does actually say that now for ordinary (non-CE) versions of Windows.
Tuesday, December 19, 2006 2:40 AM by Ema
Some Win32 APIs were added to Vista. They are callable from C.
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?
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.
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?
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.
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?
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>
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!
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.]
Thank you guys! :-)