What DLLMain lpReserved parameter really mean? - windows

One of well-known DLLMain function parameters is LPVOID lpvReserved.
From MSDN documentation:
If fdwReason is DLL_PROCESS_ATTACH, lpvReserved is NULL for dynamic
loads and non-NULL for static loads.
But what lpReserved really mean?
Is pointer to somenthing?

The quote in the question contains all the information that you are permitted to rely on:
If fdwReason is DLL_PROCESS_ATTACH, lpvReserved is NULL for dynamic loads and non-NULL for static loads.
All you are entitled to do is treat lpvReserved as a boolean that signals information about whether the load is dynamic or static (aka implicit).
It's perfectly plausible that there are versions of Windows for which lpvReserved carries more information that a plain boolean. However, that is a private implementation detail and you should not rely on that.

Related

What's the format value from the HWND returned from CreateWindow()?

Is this a memory address ranging to (theorically) 2^32-1 on 32-bit machine?
The reason I'd like to know that is I'm trying to somehow associate a HWND returned by CreateWindow() to a class instance, so in order to know how properly store that HWND value, I need to know what's the values like, so I can see what can fit better, AA array, linked list with hash table, etc.
From the documentation for MFC (to avoid confusion: this is documentation where CWnd and "window object" in the article is a C++ class in your program, not USER32):
The Windows window, on the other hand, is an opaque handle to an internal Windows data structure that corresponds to a window and consumes system resources when present.
Opaque handles must be treated as "black boxes" or atomic blobs that must not be altered and likely won't reveal any useful information through introspection either.
Also, see Wikipedia: https://en.wikipedia.org/wiki/Handle_(computing)
To store a value you need to know its type only. As documented under Windows Data Types, an HWND is a type alias for a HANDLE, which is a type alias for PVOID, which in turn is a type alias for void*.
In other words: An HWND is a pointer to unknown data. It's pointer-sized and trivially copy-able.

Including calling conventions in function declarations

I am reading about Win32 programming with C/C++ and came across a page which defines the WinMain as:
int WINAPI wWinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, PWSTR pCmdLine, int nCmdShow);
I understand most of this, except I do not understand where did the part WINAPI come from?
I know that this is a macro for a calling convention. That's not what I am seeking clarity on. My question is not on calling conventions.
When I look at Microsoft's documentation on C++ functions, and I read through optional parts of a function declaration, I don't see any mention of including a calling convention at any place in the function declaration. So where exactly does Microsoft in their documentation speak about including calling conventions in a function declaration?
The portion of Microsoft's documentation that you linked to refers to only standard components of the C++ language. Calling conventions are not part of the C++ specification.
The C++ specification describes how a function can declare its return type and parameters, but it does not define how those values are actually passed between caller and callee. Calling conventions dictate that, and different compilers/platforms implement calling conventions in their own ways. So the C++ specification doesn't describe calling conventions.
In Microsoft's documentation, calling conventions are referred to as Microsoft-Specific Modifiers to the C++ language. Which is technically correct, as any identifier that begins with 1-2 underscores in its name is a vendor-specific extension, and all of the known calling conventions begin with underscores in their names, eg:
__cdecl
__stdcall
__fastcall
__thiscall
__safecall
__vectorcall
__pascal
__fortran
__syscall
etc...
Macros like WINAPI, STDMETHODCALL, etc simply map to a specific calling convention (usually __stdcall, but sometimes __cdecl).
If omitted in a function declaration, the compiler decides which calling convention it wants to use (usually __cdecl).
Compilers from different vendors are not required to implement each others extensions. However, in the case of calling conventions, most compilers at least implement __cdecl and __stdcall, and agree on how they should work, for code portability. But make no mistake, calling conventions are still a vendor-specific extension to the standard language specification.

Windows API reserved parameters

I was wondering why some functions have some parameters that must be set to NULL because of "reserved parameters". For example:
LONG WINAPI RegQueryValueEx(
__in HKEY hKey,
__in_opt LPCTSTR lpValueName,
__reserved LPDWORD lpReserved,
__out_opt LPDWORD lpType,
__out_opt LPBYTE lpData,
__inout_opt LPDWORD lpcbData
);
I can't understand why lpReserved exists? I mean, if it's reserved why put it, wouldn't be simpler to directly omit it?
Thanks! :) (pay no attention to my English please..)
I see at least two reasons.
One would be that this parameter is reserved for future use and possible functionality extension. Making sure it's set to NULL could guarantee to some degree that in the future, when the new functionality has been added it won't break older programs.
Second possible reason would be that this parameter could actually be used internally as part of private API and public part of API dictates to set this parameter to NULL.
Why not to omit it altogether? It's much easier later to extend functionality of the system without changing the interface. It stays binary and source code compatible with the old API and does not require rebuilding of the older software.

How to best convert CString to BSTR to pass it as an "in" parameter into a COM method?

I need to convert a CString instance into a properly allocated BSTR and pass that BSTR into a COM method. To have code that compiles and works indentically for both ANSI and Unicode I use CString::AllocSysString() to convert whatever format CString to a Unicode BSTR.
Since noone owns the returned BSTR I need to take care of it and release it after the call is done in the most exception-safe manner posible and with as little code as possible.
Currently I use ATL::CComBSTR for lifetime management:
ATL::CComBSTR converted;
converted.Attach( sourceString.AllocSysString() ); //simply attaches to BSTR, doesn't reallocate it
interface->CallMethod( converted );
what I don't like here is that I need two separate statements to just construct the ATL::CComBSTR bound to the convertion result.
Is there a better way to accomplish the same task?
CComBSTR has overloaded constructors for both char* and wchar_t*, which make the call to SysAllocString() on your behalf. So the explicit allocation in your code snippet is actually unnecessary. The following would work just as well:
ATL::CComBSTR converted = sourceString;
interface->CallMethod(converted);
Furthermore, if you have no need to use the converted BSTR elsewhere in your code, you can perform the object construction in-place in the method call, like so:
interface->CallMethod(ATL::CComBSTR(sourceString));
The same applies to the _bstr_t class, which can be used instead of CComBSTR if you don't want a dependency on the ATL.
One of the confusing aspects of Windows programming is managing the conversion of Visual Basic style strings to/from C language style strings. It isn't that it is so difficult, it is just difficult to remember the details. It is usually not done often, and the MSDN documentation is so voluminous that it is difficult to find answers to your questions. But, the worst part is that you could perform some typecast that compiles fine, but doesn't work the way you expect. This results in code that doesn't work, and the bugs are hard to track down. After some experience, you learn to make sure your string conversions are doing what you expect.
C strings are arrays of characters terminated by a NULL character. Visual Basic strings differ in that the length of the string precede the characters in the string. So, a VB string knows its own length. In addition, all VB strings are Unicode (16 bits per character).
String Types
BSTR/C String conversions are required if:
You are doing COM programming in C/C++
You are writing multiple language applications, such as C++ DLL's accessed by Visual Basic applications.
One of _bstr_t constructors allows you to simply attach to existing BSTR so that you can have the exception that you want from CString::AllocSysString when BSTR allocation fails.
// _bstr_t simply attaches to BSTR, doesn't reallocate it
interface->CallMethod( _bstr_t(sourceString.AllocSysString(), false) );
The _bstr_t constructor documentation says:
_bstr_t(
BSTR bstr,
bool fCopy
);
fCopy
If false, the bstr argument is attached to the new object without making a copy by calling SysAllocString.
On the other hand, CComBSTR constructor doesn't seem to have the corresponding signature; although it can be used as well if BSTR allocation failure exception is not really needed, as mentioned by Phil Booth in his answer.

Where is using null BSTR documented?

It's at least common practice to treat null BSTR (null WCHAR* pointer) as an empty string and design all the code manipulating BSTRs accordingly. Answers to this question say the same.
Where is this practice documented? Is there any official document describing this convention?
Well, the link given in the accepted answer to that question is to an article by Eric Lippert, Eric's Complete Guide To BSTR Semantics. While it would most definitely not be official documentation, Lippert is a well know authority on COM (particularly in the scripting arena).
However, the official documentation has this to say:
A BSTR with no data elements is either an empty BSTR or a NULL BSTR. An empty BSTR indicates a present, but zero-length, data value. A NULL BSTR indicates a data value that is not present.
So, officially they are both BSTRs with no data elements, but with slightly different semantics (though there's nothing to say that those 2 cases need to be handled differently in your application). In this case, I'd certainly follow Lippert's advice of treating them identically. For me, his real-world experience with how actual implementations work carries more weight than the one sentence in the official BSTR doc.
Michael Burr gives what I think should be the accepted answer. It's unfortunate that the page for BSTR in MSDN doesn't document this practice.
In addition, you can infer this behavior from these pages in the MSDN documentation:
SysFreeString page reports that if bstr is null the function simply returns.
SysStringLen page reports that passing a null for the bstr parameter returns zero for the string length.
SysStringByteLen page reports the same behavior; null means zero length.
However, the documentation is not complete:
SysReAllocString does not mention what will happen if *pbstr is null.
SysReAllocStringLen does not mention what will happen if *pbstr is null.
Handling null BSTR as an empty string seams to be a common practice, but the technical documentation found at Microsoft actually states that there is a difference between those two.
For any document referencing both [MS-DTYP] and [MS-OAUT], specifying
BSTR in a wire representation context MUST be considered as a
reference to the transmitted BSTR type, while specifying BSTR in a
memory representation context MUST be considered as a reference to the
presented BSTR type ([MS-DTYP] section 2.2.5). Reflecting the
terminology used for presented BSTRs, a NULL BSTR, or NULL transmitted
BSTR, is defined as the wire representation of a NULL presented BSTR;
and an empty BSTR, or empty transmitted BSTR, is defined as the wire
representation of a zero-length presented BSTR. Preserving this
distinction in the wire representation enables clients and servers to
distinguish between NULL presented BSTRs and zero-length presented
BSTRs, and thus associate possibly different, application-specific
semantics to these two values.
https://msdn.microsoft.com/en-us/library/cc237580.aspx
So it's up to the implementations whether they handle both equal or not.

Resources