Patrik Stridvall ps@leissner.se writes:
Does the Windows API really define exactly what a handle is?
typedef void* HANDLE seems pretty clear to me.
I was refering some documentation that said that application should always expect a handle to be a pointer.
But never mind. Documentation and reality is often different things.
However your suggestion that any Winelib application that
cares whether
they are 32-bit or 64-bit are broken is a far too strict
IMHO and I see
no reason to require porters to fix such things.
An application that assumes that everything is 32-bit is broken, yes. I don't see why handles are any different than other types; if anything they should be less of a problem since they are supposed to be opaque, so their size should not matter for the application.
Of course most handles will fit in 32-bit, so we will still support apps that do invalid casts and truncate the handles; but this doesn't mean it is correct behavior, or that apps that do this should be able to compile without warnings.
OK, since you agree we should accept handles truncated to 32-bit, it still leaves the problem. Should API calls truncate the handles themselves ie take 32-bit integers as arguments or should they not ie take 64-bit pointers as arguments.
There is no particular reason to not accept both and make the actual definition of handle be dependent on some define and leave the choice on whether they want warnings or not to the Winelib developers, not leave them without a choice. Actually we might also consider giving them the option to accept 64-bit integers.
In short, the Winelib developers should decide what their application wants (warning wise), we shouldn't.
So therefor I suggest that we should do the following TRACE("(%p)", (LPVOID) handle);
You must be joking.
No, I'm not. However reality forced me to change the solution somewhat. See below.
I said I didn't want any typecast, and here you suggest to have one on every single debugging output.
Well, we have (or should have) a debugstr_[aw]n? on every single string in the debugging output, because we have to. We might not like it, but we have it because we must.
Let me repeat it once more just in case: *NO* *TYPECASTS*.
I know that you said that and I have said that I support that whenever possible, which it fortunately is in the normal cases.
The whole point of STRICT and pointer handles is to be able to use compiler type checks, and this is only possible without typecasts.
Agreed, but there is no self value in having no exceptions on a rule. Remember no type cast is a means no a goal.
Debugging output is hardly a critical piece of code so if we can gain something from it we should consider making an exception.
But never mind, it turns out that we we needn't make a exception either. See below.
Not to mention that your solution will probably still get a warning like "converting integer to pointer of different size" on a 64-bit platform.
Ah, thats a good point. Practice often stand in the way of a good theory. :-(
Unfurtunately I think you are right, it is more than probable that the compiler will generate such a warning, I if not now so sometime in the future.
Casting to a 32-bit integer to 64-bit pointer is almost always bogus, so there is no reason for the compiler not give a warning epecially since you can do a double cast (32-bit integer to 64-bit integer to 64-bit pointer) if you really mean it.
Fortunately the problem is solvable
#ifdef __alpha__ #ifdef STRICT #define HANDLE2POINTER(handle) (handle) #else #define HANDLE2POINTER(handle) ((void *) (unsigned long) (handle)) #endif #ifdef STRICT #define HANDLE2POINTER(handle) (handle) #else #define HANDLE2POINTER(handle) ((void *) (handle)) #endif #endif
TRACE("(%p)", HANDLE2POINTER(handle));
This solves your problem (at least for 32-bit developers) < The whole point of STRICT and pointer handles is to be able to use < compiler type checks, and this is only possible without typecasts. Francois problem < * Ignore gcc's warnings saying '%x format, pointer argument'. Fixing the format < at this stage would only introduce tons of warnings for the developpers not < participating in the switch (i.e. compiling with STRICT off). as well as my problem.
Of course we might consider making it a debug output only construct instead Like s/HANDLE2POINTER/debugptr_handle/ and define it in debugtools.h. Non-debugging parts of Wine shouldn't need to use it either since as I said earlier just pass them long or must use an explict cast to a non-void pointer.
Ah, wait a minute we will have "converting integer to pointer of different size" on 64-bit platforms for the actual cast to an object.
Of course easily solved with a similar
#ifdef __alpha__ #define HANDLE2OBJECT(type, handle) ((type *) (unsigned long) (handle)) #else #define HANDLE2OBJECT(type, handle) ((type *) (handle)) #endif
but perhaps we should have the HANDLE2POINTER (debugptr_handle) in debugtools.h all the same, nobody else is intrested in a void pointer anyway.
Of course, nothing forces us to define handles as the same both internally and externally. At least Alpha AFAIK will be binary compatible all the same, so we might not even need this. Oh well having to always using HANDLE2OBJECT is a small price to pay all the same and makes it possible for us to do adjustments on other 64-bit platforms if need be.
And yes, I'm serious. My inital solutions wasn't so good, but thanks to your feedback I have managed to refine it to a much better solution, that I think actually works in reality.
And yes, I still consider the 64-bit problem a real problem, you just tries to dismiss the problem by simply saying, that is the Winelib developers problem. Sure we could do that but, remember that Winelib is meant to help developers port application not make it more difficult by trying to enforce unnessary restriction on the code.
Sure Win64 should use 64-bit pointers as handles that is without questions, but forcing it on Win32 on 64-bit is totally unnessary, especially since I now finally after your feedback managed to find a solution that solve all your stated problems (remember that no type casts is a means not a goal and actually there will be no type casts on 32-bit (-DSTRICT) either).
But perhaps you can see any flaws in this refined solution as well?