The Design of Software (CLOSED)

A public forum for discussing the design of software, from the user interface to the code architecture. Now closed.

The "Design of Software" discussion group has been merged with the main Joel on Software discussion group.

The archives will remain online indefinitely.

Windows API specific Q

If this offends you just tell me to pee off, I won't mind too much :-) There are more specific places to ask, perhaps, but the quality of the answers around here tends to be better.

If I want to add an object pointer to a window using SetWindowLong is there a safe way of deciding whether the data I later retrieve (using GetWindowLong) is a pointer to my object or not? Of course I can use reinterpret_cast but that isn't safe because it could be some other data, so I was wondering how other people get around the problem.

Tuesday, December 20, 2005
 
 
You could store a separate mapping from HWNDs to your pointers, which would avoid the issue.

Otherwise, here are three techniques I've used in this kind of situation:

1) Add one to the value before you store it.  Most data stored in this way is a pointer, and so will almost always be an even number.  By storing odd numbers, you get a very quick sanity check.

2) Use IsBadReadPtr to check that the value is a valid pointer before you try to follow it.

3) Put one or more magic numbers at the start of whatever structure you're pointing at, and check those numbers before relying on the pointer.

If all three checks pass, you can be pretty sure you've got one of your pointers.  If one of them fails, it will fail safely.
Richie Hindle Send private email
Tuesday, December 20, 2005
 
 
> 3) Put one or more magic numbers at the start of
> whatever structure you're pointing at, and check
> those numbers before relying on the pointer.
>  -- Richie Hindle


I program for embedded CPUs, but I use Richie's Method #3 to validate pointers to objects.  Every object has a 'Type' variable that should at least be 32-bit or 64-bit & is initialized to a specific magic number & NEVER modified.

When passed a pointer, the object API functions can check this 'Type' for the expected magic number value.  If the magic number value is NOT present, then the pointer &/or the object is corrupt.


In addition, I usually code the magic numbers to represent the object types in ASCII (accounting for endianess & data word-size of the processor).  This allows the user to quickly verify the object's type in a debugger watch window or printing out a short ASCII string (of known length).

For example, timer objects would code the the magic number to spell "TMR " in ASCII :

#if (ENDIAN_TYPE == ENDIAN_TYPE_BIG)
#define TYPE_NONE 0x4E4F4E45 /* "NONE" in ASCII. */
#define TYPE_TMR  0x544D5220 /* "TMR " in ASCII. */

#else

#if (DATA_SIZE == WORD_SIZE_32)
#define TYPE_NONE 0x454E4F4E /* "NONE" in ASCII. */
#define TYPE_TMR  0x20524D54 /* "TMR " in ASCII. */

#elif (DATA_SIZE == WORD_SIZE_16)
#define TYPE_NONE 0x4F4E454E /* "NONE" in ASCII. */
#define TYPE_TMR  0x4D542052 /* "TMR " in ASCII. */

#else                        /* Dflt WORD_SIZE_08*/
#define TYPE_NONE 0x4E4F4E45 /* "NONE" in ASCII. */
#define TYPE_TMR  0x544D5220 /* "TMR " in ASCII. */

#endif
#endif
Ian Johns
Tuesday, December 20, 2005
 
 
> You could store a separate mapping from HWNDs to your pointers, which would avoid the issue

I could, in fact since there doesn't seem to be a neat solution I probably will, but using the window data seemed to be a natural fit for the basic problem (as you correctly spotted - mapping a window handle to an object). It was only later that I spotted the hidden nasty that is the "it could be any old data in there" problem.

Thanks, both of you.

Tuesday, December 20, 2005
 
 
You can check to see if GetWindowLongPtr gives you back 0 for GWLP_USERDATA. If it does, you didn't set the data yet; if it gives you back something else, you did, and it's your data.

Since, then, you know it's your data, but it's a LONG_PTR, and you want a whatever *, reinterpret_cast is actually perfectly safe.

You could, then, become paranoid, and wonder whether someone else could set the data behind your back, so it appears to be valid (not 0), but is actually not valid. Well, they could, but I wouldn't worry about it, and indeed I've never seen this happen.

But if you must remaind paranoid, you can use SetProp to tag a window with a named property. You could generate a GUID for the name, I guess, to ensure uniqueness.

You could then become even more paranoid, and figure that somebody could find your property, and change it to something else -- well, they could...

Really, this could go on forever! The only way to be sure is to store off a pointer to your original data, and check the value you got back is the same -- which rather defeats the purpose.

Honestly, just don't worry about it :)
Tom_
Wednesday, December 21, 2005
 
 
Actually I can't assume that the data returned is my data (my situation may be unusual, but is not unique), that was why I asked. Actually I've had a rethink since yesterday and am not going to use the mapping between hwnds and my objects at all, so I'm basically following your advice and just not worrying about it :-)

Wednesday, December 21, 2005
 
 

This topic is archived. No further replies will be accepted.

Other recent topics Other recent topics
 
Powered by FogBugz