Date: | March 3, 2005 / year-entry #54 |
Tags: | code |
Orig Link: | https://blogs.msdn.microsoft.com/oldnewthing/20050303-00/?p=36293 |
Comments: | 35 |
Summary: | The window manager provides a pointer-sized chunk of storage you can access via the GWLP_USERDATA constant. You pass it to the GetWindowLongPtr function and the SetWindowLongPtr function to read and write that value. Most of the time, all you need to attach to a window is a single pointer value anyway, so the free memory... |
The window manager provides a pointer-sized chunk of storage you can access via the Note that this value, like the other window extra bytes and the messages in the |
Comments (35)
Comments are closed. |
Works in 99% of the cases… in the rest 1%, some third party component and/or simply other part of the code is using same place to store something else…
On Windows CE this happens almost certainly…
First a scratch windows, then GWL_USERDATA – are we going toward a CWindow sample?
Can someone tell me why one would use GWL_USERDATA, rather than just use the SetProp / GetProp functions to store a pointer to data? Sorry if this is a stupid question, I do not know much about programming for Windows, but I am trying to learn.
JDM: I believe people use GWLP_USERDATA rather than GetProp/SetProp for performance reasons. Looking up the pointer on every message a window processes can add up quickely. GetWindowLongPtr() is a very direct way to get a bit of data stored with a window. GetProp probably requires hashing a string to do a table look-up and is thus a lot more instructions.
GetWindowLongPtr() can be used in a set-and-forget fashion. If you add properties to a window, you have to be careful to remove them all when the window is destroyed to avoid wasting system resources. (That’s not to say that you can forget about cleaning up the data structure pointed to by your pointer.)
Raymond, do you mean that the window class decides what GWLP_USERDATA will be used for (for example for a pointer to the C++ object of type X that manages the window)? I assume the actual pointer stored there is still per-window and not per-class.
Adrian – actually, you can short circuit the GetProp lookup by creating an ATOM from a string (eg. the window class name for sake of argument), and using that instead of the string.
This is what winforms in .NET does under the hood.
Even with the ATOM, the proper entry has to be located. GWLP_USERDATA should be much faster. However, in the context of an application, the difference would be very insignificant.
When was GetProp/SetProp introduced?
One apon a time I had a project where I had to write some "middleware" (if that’s the correct buzzword for it these days) between the Windows API and some cross-platform UI classes. I found that this userdata area was a great place to hook on each window’s instance of a class in the underlying library so I could then dispatch the appropriate events on it.
However, I was a bit naughty because I was attaching these objects to windows of built-in classes (BUTTON in particular). It worked, and at the time I didn’t really think anything of it, but I guess it’s a good thing that none of the classes I used had their own userdata… or are applications allowed to attach userdata to windows of classes owned by others?
When I wrote that the values "belong to the window class", I meant that only the window class implementor may read or write the values. Think of them as private members of the window class. Code that calls CreateWindow is a customer of the window class and should not be messing with the window class’s private data without permission.
Actually, I bet the "don’t store stuff in GWLP_USERDATA on windows you didn’t write" belongs in the "What would happen if everyone did this?" category.
Since there is only one resource and no locks, the conclusion is that there must only be one owner, and the window implementation is the natural place.
As I recall, GetProp and PutProp were in Windows 2.x.
Interesting. I’m checking into that. But even if it does belong to the creator of the window, enough window class implementations use it that you still should stay away for safety’s sake.
Tim Smith-
Well, if you care about lookup time at all, you should really be using ATL’s assembly language thunking mechanism to hook your windows instead of GWLP_USERDATA anyway – it’s even faster, and has none of the problems of others potentially colliding with your userdata parameter.
Raymond, you have the sublety of MSDN with this one…
"belongs to the window class and not to the code that creates the window."
In other words, if you are CreateWindow()ing a window implemented by someone else, do *not* set the window extra bytes — they are reserved for the window class implementation and you don’t know if they are using them.
We most of us VC dotNet 2003. Is the warning about the GetWindowLongPtr function being unsafe for Win64 fixed in new versions of Windows header file? The problem is that in 32-bit, it’s remapped with a define to GetWindowLong!
This is the extra you are asking
with the cbWndExtra member of
WNDCLASS when you register the class,
or is somehing different?
If it is, there is nothing new.
And you can get the some "per class" data if you use cbClsExtra.
GWLP_USERDATA
Retrieves the user data associated with the window. This data is intended for use by the *application that created* the window. Its value is initially zero.
This is the built-in extra you get with the cbWndExtra set to zero.
Mihai, no it’s different. It has nothing to do with cbWndExtra. Every single window intance has it. cbWndExtra/cbClsExtra will apply only to class you register yourself, GWL_USERDATA is available in HWNDs registered by others too
Raymond, in my experience, none of the Windows controls use it (that statement isn’t true for CE though). Frankly, I don’t have much experience with third party window classes, so I don’t know how often GWL_USERDATA is in use, but it is very convinient place to store your data. That’s what the imply anyway – USERDATA. A simple assert could warn if it is already in use.
It seems that safest way is to use GetProp/SetProp with some GUID as a property name. Problem is that one should take care of cleaning up properties when window is destroyed
Chris Becke,
I remember that (first) problem from when I was doing my project I mentioned earlier in the discussion. As I recall, I worked around it by simply ignoring messages that arrived with no object pointer attached, so I missed a few messages on window creation. At the time I knew that was a bad idea, but I couldn’t see any way around it that didn’t involve really convulted code so I left it in.
Fortunately, thus far it hasn’t caused any problems, and Microsoft’s famous commitment to backward compatibility will hopefully keep it that way! ;)
Chris/Ben: This topic is drifting. You can put suggestions for future topics into the Suggestion Box. If you post a suggestion as as a comment to a regular article it will get lost in the mists of time. (By the way, as far as I can tell WM_SIZE comes after the creation messages.) There is already a brief series planned for July on a closely-related subject.
gdt – because people will write code like this:
class MyWnd {
…
LRESULT MyWndProc(…) {
case WM_USER_MSG:
DestroyWindow(m_hWnd);
m_bar = m_foo.CrashWithAccessViolation();
return 0;
case WM_NCDESTROY:
delete this;
return 0;
}
};
… which will crash.
Even worse is when they write code like this:
case WM_DESTROY:
delete this;
return 0;
… which nearly guarantees a crash.
Never mind the fact that this whole GWLP_USERDATA pointer mapping mechanism is a godawful way of doing it that should have died out a long time ago, but MFC kept it around.
For a server-type application, you’ll find to your dismay that all of your window properties are recycled when the user logs out.
I can’t for the life of me find the reference right now.
Then again, your service shouldn’t be displaying UI either.
Hi Simon Cooke, what is the alternative solution for the pointer mapping?
MFC doesn’t use GWLP_USERDATA. MFC installs a window creation hook, which gets called before the first message arrives, and in there maps the window handle against the class pointer in a global hash map.
Actually, this all begs the question – why on earth does the window manager send messages before WM_CREATE/WM_NCCREATE ?
If I write a very simple window class that I want to embed ona dialog – or otherwise allow consumers to create with CreateWindow… well, I write in C++ and its natural for me to manage my data in a class associated with the window. GWL_USERDATA is the natural place to store my class pointer. The problem is, the seemingly logical and niavely simple "new CMyWind" in WM_CREATE and "delete this" in WM_DESTROY just dont work as one at least gets an extraneous WM_SIZE before any creation messages, leading to a window proc with convoluted just-in-time creation of class data.
This gets even worse when someone writes a CMyAppWindow that both wraps and implements a window. In which case the class is created up front, its constructor registers a window class and creates it. Which starts out simple and quickly turns into a mess when you realize theres no neat way to get the window <-> c++ class bound together. You cant do a SetWindowLong(CreateWindow(… to tell the WindowProc what the class instance pointer is as the WindowProc is invoked before CreateWindow returns. You cant even pass the class instance as the CREATEPARAM as you *still* miss a bunch of messages that arrive before WM_NCCREATE and WM_CREATE.
I really wish the guys responsible for the window manager had made what should be simple, well, simple.
Chris – it is simple. You’re just doing it the wrong way. You should create your object instance *before* attaching a window to it. You should also destroy your object instance *after* the attached window has been fully destroyed.
WM_DESTROY isn’t the place to do that kind of teardown anyway – WM_NCDESTROY might be.
Doing "delete this" on wrapped Windows is a lame idea anyway (your object needs to live longer than its HWND). But if you *really* need to do it, you could have a static WNDPROC that you poke into the window instance (using SetWindowLong) that handles the final set of messages your class gets after your object has been destroyed. Of course the trick at that point is making sure that you don’t have any other calls to your WNDPROC still waiting to be serviced when you unwind your way through the stack.
Just say NO to delete this. It has only one use as far as I’m concerned – handling destruction of object instances during calls to Release on COM objects. For nearly every other circumstance, you’re doing the wrong thing, and you should seriously reconsider before letting it into production code.
Think of it as the C++ equivalent of goto. You should only use it if you’re really damn certain that you should use it.
Well, if you want to write an old fashioned type window that can, for example, be embedded in a dialog resource, then the CreateWindow *must* come first, and the creating app is possibly not written in C++ or know how to create your class.
In which case youre stuck doing essentially a ‘delete this’ in your WM_DESTROY code as the only signal that the consuming app is finished with your control.
This style of control seems to be a bit of a lost art :/
Jorg – use thunks instead. See the ATL source code, or this article:
http://groups-beta.google.com/group/comp.os.ms-windows.programmer.ole/msg/9797b81ce52c7ffb?dmode=source
Sebastian –
OK; I’m wrong on the GWLP_USERDATA, but it’s a similar idea. It’s not a window creation hook (at least in older MFCs – not sure about 7.0), but is a generic MFC window which attaches the window to its C++ object in the generic window’s WM_NCCREATE handler. After that, you have this walk through an associative map for the HWND to C++ pointer… it’s just painful.
Chris Becke –
Sure, go ahead, but the LAST message your window will get is WM_NCDESTROY, *NOT* WM_DESTROY so you’d better hope that your WNDPROC implementation doesn’t use any member variables or your app is toast after that delete this call.
As for creating a window which can be embedded in a dialog resource of an App that *you* don’t control, that’s what ActiveX is for – and it controls lifetime management in those circumstances.
If you control the dialog creation code you have other options though – you can replace the window after dialog creation with one of your choosing, or you could walk through the dialog template looking for windows of your own class type and implement their creation yourself.
That doesn’t change the fact that delete this can lead to dangerous side effects in production code if everyone who will ever touch that code doesn’t know exactly what the circumstances are that the window wrapper can be torn down in.
Rather than a delete this, you’d at least want to add some kind of re-entrancy protection to the Wndproc, or a refcount to the object so that you don’t pull it out from unsuspecting others.
3/4/2005 10:54 AM Raymond Chen
> Then again, your service shouldn’t be
> displaying UI either.
I used to think so too. But I want things like antivirus and firewall programs to start before anyone logs in, and I want to be notified when they detect anything. Perhaps the UI should be done by a separate program that gets started during login, but at least for antivirus we don’t usually want the logged-in user to be able to kill it.
Then don’t let the logged-in user kill the anti-virus checker. The service does the anti-virus checking and the UI part just does the UI. If the user kills the UI part, the service keeps running.
Norman: Threads associated with the same desktop can use window messages to inject arbitrary code into each other and cause it to run (this is called a "Shatter attack"). So if a service displays UI, the logged-in user can kil it, or worse. There are ways to filter out such messages, and WM_TIMER is now blocked by the OS from being sent across processes, but it’s extremely hard if not impossible to catch all the messages that could be used for such an attack. This is the reason for the advice not to let services display UI directly.
(Nevertheless, messages received by the Messenger service are still displayed by the CSRSS process which runs as SYSTEM. I think all the services vulnerable to this exploit are disabled by default in XP SP2 though.)
I asked around and guidance is "unclear", though leaning slightly towards "it belongs to the person who called CreateWindow". For safety’s sake, then, you should just avoid it unless you can establish clear ownership.
Surely it should belong to the person who called RegisterClass, because it’s the class that defines where the wndproc is, and it’s the wndproc which is almost always going to be what’s looking at the memory in question?
I can’t see the sense in making it belong to the person calling CreateWindow. If they’re not defining the class (and hence the wndproc) why should they have any interest in this kind of thing?