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.
Related
I'm looking for confirmation on this windows programming idiom, am I correct in thinking that many different types of "handles" are passed around as not only LRESULT objects but also lParam and wParam objects?
I'm guessing that as long as we know "what" type of handle is in LRESULT or lParam/wParam we can cast back into it.
For example
case WM_CREATE:
...
//create a window
//lParam is the CREATESTRUCT for new window created here
....
return lParam;
...
...
CREATESTRUCT cStruct = (CREATESTRUCT)SendMessage(hwnd, msg /*WM_CREATE*/);
cStrcut.cx;//this is the width of the new window?
correct?
Is this is "correct"? Can anyone provide me and the StaticOverflow community a short thesis on this technique/idiom?
Questions:
Should we only return lParam (or only wParam) values?
Are there any pitfalls one should know about?
Both LRESULT and LPARAM are LONG_PTR types, which are 32 or 64 bit integers. I'm not a seasoned C programmer, but it appears these integers are just being used as "buffers" which the programmer later casts into their "real" type before using... sound accurate?
This style of programming is "bad" as there is no way to know what something really is at compile-time. That said, as the WIN32 API is a C API (instead of say, C++), there's not much else that can be done when one wants to pass around any type of struct using the same method signature.
So, the API design team decided to have two parameters to handle this. A 32-bit LPARAM and a 16-bit WPARAM.
When working with the Win32 C API, you're just going to have to make sure you read the documentation correctly and ensure you're casting to the right thing that the documentation says it is.
So to answer your question, you are correct - but only because you have no other choice. In an attempt to be complete here, MFC came along (for C++ programmers), but that isn't considered a good object-orientated library - it's more of a wrapper. There are others out there that do a much better job (e.g. wxWidgets).
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.
This is Line 519 of WinNT.h (BUILD Version: 0091)
#define DECLARE_HANDLE(name) struct name##__{int unused;}; typedef struct name##__ *name
Why do we need a pointer to an struct with a single int member with a weird name called unused?
And will we ever need to use a line of code like this one?
HINSTANCE hInstance = new HINSTANCE__;
Overall declaring different data types with the same structures, doesn't make sense to me. What's the idea behind this?
DECLARE_HANDLE(HRGN);
DECLARE_HANDLE(HRSRC);
DECLARE_HANDLE(HSPRITE);
DECLARE_HANDLE(HLSURF);
DECLARE_HANDLE(HSTR);
DECLARE_HANDLE(HTASK);
DECLARE_HANDLE(HWINSTA);
DECLARE_HANDLE(HKL);
The point is for the different handles to have different types so that, for example, a HINSTANCE isn't assignable to a HANDLE. If they were all defined as "void*", then there are classes of errors that the compiler could not detect.
And will we ever need to use a line of code like this one?
HINSTANCE hInstance = new HINSTANCE__;
You usually use a HINSTANCE value returned by a Windows system call; I have never seen code executing a line like that.
They don't actually point to anything to memory; they are just used to refer to objects (files, resource, semaphores, windows) when making calls to the Windows API. While they're nothing more than just indexes into kernel's object tables, the developers decided that they make it a pointer to an unused structure which would make them "opaque" and cause less confusion between other types. The DECLARE_HANDLE is a function macro that does just that - declaring opaque types for handles.
The HINSTANCE of a win32 application is passed to WinMain, but is there any other way of determining the current HINSTANCE (in case you couldn't tell, I'm very new to win32 programming!)? I need to create a window inside of a library and (since the library is cross platform), id prefer not to have to pass it in.
If memory serves, GetModuleHandle(NULL); returns the instance handle.
__ImageBase is your friend, especially in the case of libraries.
Note that the linked blog post (by R. Chen, although not the same post as the one linked by Brian Bondy) is worth reading (including the comments!)
If you are using MFC, you can use AfxGetInstanceHandle.
If you are not using MFC you can use: GetWindowLong(hWnd, GWL_HINSTANCE)
The function AfxGetStaticModuleState() does the trick.
If you call it within a dll, the functions returns the handle to the dll, if the call within a exe it returns the handle to the executable.
DWORD size;
TCHAR fileName [MAX_PATH];
HMODULE hModule = AfxGetStaticModuleState()->m_hCurrentInstanceHandle;
::GetModuleFileName (hModule, fileName, size);
What's the meaning of BSTR, LPCOLESTR, LPCWSTR, LPTSTR, LPCWCHAR, and many others if they're all just a bunch of defines that resolve to wchar_t anyway?
LPTSTR indicates the string buffer can be ANSI or UNICODE depending on the definition of the macro: UNICODE.
LPCOLESTR was invented by the OLE team because it switches its behaviour between char and wchar_t based on the definition of OLE2ANSI
LPCWSTR is a wchar_t string
BSTR is an LPOLESTR thats been allocated with SysAllocString.
LPCWCHAR is a pointer to a single constant wide character.
They're actually all rather different. Or at least, were at some time different. Ole was developed - and needed - wide strings while the windows API was still Win16 and didnt support wide strings natively at all.
Also, early versions of the Windows SDK didnt use wchar_t for WCHAR but unsigned short. The windows SDK on GCC gets interesting as - im led to belive that GCC 32bit has a 32bit wchar_t - on compilers with 32bit wchar_t, WCHAR would be defined as an unsigned short or some other type thats 16bits on that compiler.
LPTSTR and LPWSTR and similar defines are really just defines. BSTR and LPOLESTR have special meanings - they indicate the the string pointed to is allocated in a special way.
String pointed to by BSTR must be allocated with SysAllocString() family functions. String pointed to by LPOLESTR is usually to be allocated with CoTaskMemAlloc() (this should be looked up in the documentation to the COM call accepting/returning it).
If allocation/deallocation requirements for strings pointed to by BSTR and LPOLESTR are violated the program can run into undefined behaviour.
MSDN's page on Windows Data Types might provide clarification as to the differences between some of these data types.
LPCWSTR - Pointer to a constant null-terminated string of 16-bit
Unicode characters.
LPTSTR - An LPWSTR if UNICODE is defined, an LPSTR otherwise.