Answered by:
Getting HANDLE as a returned parameter...

Question
-
Hello,
In my C# program I'm attempting to call Win32 functions located inside a DLL. These functions are all specified using the standard Win32 data types such as DWORD, LPVOID, etc. I've been able to determine the C# equivalents for most of those I need and I've gotten the corresponding functions to work except for those using type HANDLE. For example, one of the functions gets an appropriate HANDLE then passes it back to the caller in a HANDLE parameter:
void GetHandle(HANDLE h);
My understanding is that the C# equivalent of HANDLE is System.IntPtr. It seems that appropriate approach would be to create an object of type System.Int (but there is no such type), then pass its address to GetHandle as follows:
System.Int obj;
GetHandle(&obj);
However, since there is no such System.Int type I tried the following instead:
System.Int32 obj;
GetHandle(&obj);
However, that simply did not yield the correct results from GetHandle. I tried several other things but I really hate just "trying" things without actually knowing what I'm doing. So, what is the proper approach? I'd like this to work for both 32-bit and 64-bit Windows without having to change my code if possible.
Thanks,
RaySaturday, July 10, 2010 11:15 PM
Answers
-
If the native C/C++ DLL actually has a function with that signature, then there's something wrong :
void GetHandle(HANDLE h)
{
h = GetDesktopWindow();
}void Foo()
{
HANDLE h = 0;
GetHandle(h); // h will still be 0A more workable soltion would be:
HANDLE GetHandle();
And in C# this would be:
IntPtr handle = GetHandle();
http://blog.voidnish.comSaturday, July 10, 2010 11:26 PMModerator -
Well stuck with it or not the signature you gave can't ever return a value in h, not in C# not in C not in C++
Are you sure the original C signature isn't
void GetHandle(HANDLE *h);
which would translate to
void GetHandle(out IntPtr handle);
?
Sunday, July 11, 2010 2:48 AM -
Hello,
In my C# program I'm attempting to call Win32 functions located inside a DLL. These functions are all specified using the standard Win32 data types such as DWORD, LPVOID, etc. I've been able to determine the C# equivalents for most of those I need and I've gotten the corresponding functions to work except for those using type HANDLE. For example, one of the functions gets an appropriate HANDLE then passes it back to the caller in a HANDLE parameter:
void GetHandle(HANDLE h);
My understanding is that the C# equivalent of HANDLE is System.IntPtr. It seems that appropriate approach would be to create an object of type System.Int (but there is no such type), then pass its address to GetHandle as follows:
System.Int obj;
GetHandle(&obj);
However, since there is no such System.Int type I tried the following instead:
System.Int32 obj;
GetHandle(&obj);
However, that simply did not yield the correct results from GetHandle. I tried several other things but I really hate just "trying" things without actually knowing what I'm doing. So, what is the proper approach? I'd like this to work for both 32-bit and 64-bit Windows without having to change my code if possible.
Thanks,
Ray
This is not making sense, the example you give is:void GetHandle(HANDLE h);
If this is the signature of the unmanaged function, then there is no address, there is ONLY a handle and that handle is passed IN. No unmanaged function with that signature could modify the value of HANDLE as seen by the caller.
Let be clear, what EXACTLY is the function signature of the function you want to call, this is easy to solve once we know this.
Incidentally a HANDLE (In Windows) is NOT a pointer, it is not an address nor does the OS treat it as an address.
It is a 32 bit integer on 32-bit OS and a 64-bit integer on a 64-bit OS - it is stored in a HANDLE type which is defined as a void *.
However it is JUST a number, NOT a pointer, it is stored in a pointer for convenience because the size of a pointer is 32-bits on 32-bit OS and 64-bits on a 64-bit OS, if they used some other type (Int32, UInt64 and so on) then this would be the same size on both kinds of OS.
So think of a HANDLE as an integer whose size depends on the kind of OS.
Cap'n
- Marked as answer by Harry Zhu Monday, July 19, 2010 8:37 AM
Monday, July 12, 2010 12:26 AM
All replies
-
If the native C/C++ DLL actually has a function with that signature, then there's something wrong :
void GetHandle(HANDLE h)
{
h = GetDesktopWindow();
}void Foo()
{
HANDLE h = 0;
GetHandle(h); // h will still be 0A more workable soltion would be:
HANDLE GetHandle();
And in C# this would be:
IntPtr handle = GetHandle();
http://blog.voidnish.comSaturday, July 10, 2010 11:26 PMModerator -
Nishant,
I agree that a function returning a HANDLE would be preferable. However, the function I gave as an example is what I am stuck with using since it is already in the 3rd party DLL I am using. Therefore, I have no choice but to receive the HANDLE as a parameter rather than a return value.
Ray
Sunday, July 11, 2010 2:30 AM -
Well stuck with it or not the signature you gave can't ever return a value in h, not in C# not in C not in C++
Are you sure the original C signature isn't
void GetHandle(HANDLE *h);
which would translate to
void GetHandle(out IntPtr handle);
?
Sunday, July 11, 2010 2:48 AM -
Nishant,
I must be missing something pretty basic then. Functions like scanf, time, fgetpos, etc. all have pointer parameters. When called these fucntions merely store something in the addresses specified by those parameters, then return. So, if type HANDLE is really nothing more than a pointer type, why can't a function that has a type HANDLE parameter store something in the address specified by that parameter in the same way? In all cases, of course, that pointer better point to a valid object before the call is made.
Ray
Sunday, July 11, 2010 4:16 AM -
While it's common for HANDLE to be a typedef for void*, it's not guaranteed. All that's guaranteed is that sizeof(HANDLE) is equal to sizeof(void*). You'll find that HANDLE arguments are rarely used as a pointer. In your example, the HANDLE is passed by value. So it cannot be used to return a value back from the function.
http://blog.voidnish.comSunday, July 11, 2010 4:21 AMModerator -
Thanks Nushant,
But I'm afraid that this brings me back to my original issue. Since the 3rd party DLL vendor has chosen to use HANDLE as a parameter, it's obviously being used as a pointer in this case. Of course, simply knowing that it is a void * doesn't really help. Since there must be a real object type hidden beneath that void * somewhere, my task is to discover what type it is and provide a pointer to that type as an argument. From what I can gather from Web searches it is likely to be and Int32 (maybe an Int64 for 64-bit Windows?), but I don't seem to be able to get that to work properly. I suppose I can contact the vendor, but I'm sure you already know the futility of trying to discuss something at this level with anyone at tech support:-)
Thanks for your help,
RaySunday, July 11, 2010 4:41 AM -
Assuming that's so, you still need to know what the method does or returns. And what you could do is use the Marshal class and allocate some memory equal to sizeof(HANDLE), and then pass an IntPtr that represents this allocated native memory to your 3rd party method. Assuming that your idea that it uses it as a pointer is correct, then when the function ends, the memory pointed to by the IntPtr will itself be a pointer to some struct or other data format created or allocated by the native method. How you use it depends on what that data is. Your best bet is to get some example native code that calls and uses this DLL. Then you will have a much better idea of what to do to port to C#.
Once again, I don't personally believe that any decent 3rd party library would ever use a HANDLE in such a manner. So my above answer was purely hypothetical so as to let me go along with your train of thought :-)
http://blog.voidnish.comSunday, July 11, 2010 4:51 AMModerator -
Hello,
In my C# program I'm attempting to call Win32 functions located inside a DLL. These functions are all specified using the standard Win32 data types such as DWORD, LPVOID, etc. I've been able to determine the C# equivalents for most of those I need and I've gotten the corresponding functions to work except for those using type HANDLE. For example, one of the functions gets an appropriate HANDLE then passes it back to the caller in a HANDLE parameter:
void GetHandle(HANDLE h);
My understanding is that the C# equivalent of HANDLE is System.IntPtr. It seems that appropriate approach would be to create an object of type System.Int (but there is no such type), then pass its address to GetHandle as follows:
System.Int obj;
GetHandle(&obj);
However, since there is no such System.Int type I tried the following instead:
System.Int32 obj;
GetHandle(&obj);
However, that simply did not yield the correct results from GetHandle. I tried several other things but I really hate just "trying" things without actually knowing what I'm doing. So, what is the proper approach? I'd like this to work for both 32-bit and 64-bit Windows without having to change my code if possible.
Thanks,
Ray
This is not making sense, the example you give is:void GetHandle(HANDLE h);
If this is the signature of the unmanaged function, then there is no address, there is ONLY a handle and that handle is passed IN. No unmanaged function with that signature could modify the value of HANDLE as seen by the caller.
Let be clear, what EXACTLY is the function signature of the function you want to call, this is easy to solve once we know this.
Incidentally a HANDLE (In Windows) is NOT a pointer, it is not an address nor does the OS treat it as an address.
It is a 32 bit integer on 32-bit OS and a 64-bit integer on a 64-bit OS - it is stored in a HANDLE type which is defined as a void *.
However it is JUST a number, NOT a pointer, it is stored in a pointer for convenience because the size of a pointer is 32-bits on 32-bit OS and 64-bits on a 64-bit OS, if they used some other type (Int32, UInt64 and so on) then this would be the same size on both kinds of OS.
So think of a HANDLE as an integer whose size depends on the kind of OS.
Cap'n
- Marked as answer by Harry Zhu Monday, July 19, 2010 8:37 AM
Monday, July 12, 2010 12:26 AM -
Nishant,
I must be missing something pretty basic then. Functions like scanf, time, fgetpos, etc. all have pointer parameters. When called these fucntions merely store something in the addresses specified by those parameters, then return. So, if type HANDLE is really nothing more than a pointer type, why can't a function that has a type HANDLE parameter store something in the address specified by that parameter in the same way? In all cases, of course, that pointer better point to a valid object before the call is made.
Ray
You are missing something - A HANDLE is not a pointer, period. (it just happens to be convenient to store then in void * variables). They are not pointers, they cannot be dereferenced or used for address calculations. Just pretend that HANDLE is like DWORD, just a type for storing a number and never used or treated as a pointer.This is the cause of your confusion.
Cap'n
Monday, July 19, 2010 11:44 AM -
Thanks Nushant,
But I'm afraid that this brings me back to my original issue. Since the 3rd party DLL vendor has chosen to use HANDLE as a parameter, it's obviously being used as a pointer in this case. Of course, simply knowing that it is a void * doesn't really help. Since there must be a real object type hidden beneath that void * somewhere, my task is to discover what type it is and provide a pointer to that type as an argument. From what I can gather from Web searches it is likely to be and Int32 (maybe an Int64 for 64-bit Windows?), but I don't seem to be able to get that to work properly. I suppose I can contact the vendor, but I'm sure you already know the futility of trying to discuss something at this level with anyone at tech support:-)
Thanks for your help,
Ray
If the vendor passes a HANDLE (this is a typdef defined in Windows.h incidentally) then it is an input-only operation, and by convention one expects to only ever see a true OS handle stored in such a variable. Because of these factors it is impossible to return anything at all unless we do something unconventional.Of course a programmer could choose to store a real pointer in a HANDLE variable, but that would be very bad practice because it just confuses people.
If a pointer (a proper address) really is expected by the unmanaged function then it should be declared as taking 'void *' or some other type *, but not HANDLE.
Contact the vendor for a definite explanation and signature for this function, without this we are just guessing and speculating and this is a waste of time.
Cap'n
Monday, July 19, 2010 11:51 AM -
Just to add a bit to the previous responses:
Sometimes you might want to use SafeHandle or HandleRef instead of IntPtr for handle values used by Windows API functions:
Also see http://www.pinvoke.net for more information about specific Windows API functions.
Monday, July 19, 2010 12:26 PM