WinAPI that returns a funtion ptr

D

Dragon

Hello,

I was translating some sample from MSDN from C to VB .NET, and got the
following:

~
Private Declare Function GetProcAddress Lib "kernel32.dll" (ByVal hModule As
IntPtr, <MarshalAs(UnmanagedType.LPStr)> ByVal lpProcName As String) As
<MarshalAs(UnmanagedType.FunctionPtr)> DLLGETVERSIONPROC

Private Delegate Function DLLGETVERSIONPROC(ByRef dvi As DLLVERSIONINFO) As
Integer


Private Function GetDllVersion(ByVal lpszDllName As String) As Integer

Dim hinstDll As IntPtr

Dim dwVersion As Integer = 0

hinstDll = LoadLibrary(lpszDllName)

If hinstDll.ToInt32 <> 0 Then

Dim pDllGetVersion As DLLGETVERSIONPROC

pDllGetVersion = GetProcAddress(hinstDll, "DllGetVersion")

If Not pDllGetVersion Is Nothing Then

Dim dvi As DLLVERSIONINFO

Dim hr As Integer

dvi.cbSize = Marshal.SizeOf(dvi)

hr = pDllGetVersion.Invoke(dvi)

If SUCCEEDED(hr) Then

dwVersion = PACKVERSION(dvi.dwMajorVersion, dvi.dwMinorVersion)

End If

End If

FreeLibrary(hinstDll)

End If

Return dwVersion

End Function

~



When I call this function, an error box pops out:

An unhandled exception of type 'System.ArgumentException' occurred in
WinApp.exe
Additional information: äÅÌÅÇÁÔ ÎÅ ÓÏÚÄÁÌ ÕËÁÚÁÔÅÌØ ÎÁ ÆÕÎËÃÉÀ.
(Translation: Delegate haven't created the function pointer.)

If I declare GetProcAddress as Integer it returns normal value, so it's
probably a marshalling problem.
Can I do something to get a delegate value?

Thanks in advance.
 
M

Mattias Sjögren

Can I do something to get a delegate value?

No, in .NET v1.x this is not supported.



Mattias
 
D

Dragon

No, in .NET v1.x this is not supported.

Bad, bad, too bad... 8=[
Is there another approach?
 
D

Dragon

Thanks for great sample. Though, my actual question was: can I execute
function whose address was given by API function.

By the way, can I define a ByRef parameter using this MethodBuilder
approach, or I should define it as IntPtr and use GCHandles for getting an
address?

Thanks
 
M

Mattias Sjögren

Thanks for great sample. Though, my actual question was: can I execute
function whose address was given by API function.

Not in VB.NET v7.x you can't. Other languages such as C++ and IL
assembler lets you do it though. And in v2.0 of the framework there's
a way to create a delegate for an arbitrary functon pointer.

By the way, can I define a ByRef parameter using this MethodBuilder
approach, or I should define it as IntPtr and use GCHandles for getting an
address?

Yes you can, but to create a ByRef Type in v1.x of the framework you
have to pass the typename with a "&" appended to
System.Type.GetType().



Mattias
 
D

Dragon

Thanks Mattias.

Unfortunately I can't get the ByRef parameter to pass value back. I call

Dim RetVal As Integer = CInt(t.InvokeMember("DllGetVersion",
BindingFlags.InvokeMethod, Nothing, Activator.CreateInstance(t), New
Object() {dvi})),
where t is Type object.

RetVal equals to 0, so function succeeds, but dvi (DLLVERSIONINFO structure)
doesn't have any members changed.

How can I get it passed?

Thanks again.
 
M

Mattias Sjögren

Unfortunately I can't get the ByRef parameter to pass value back. I call
Dim RetVal As Integer = CInt(t.InvokeMember("DllGetVersion",
BindingFlags.InvokeMethod, Nothing, Activator.CreateInstance(t), New
Object() {dvi})),
where t is Type object.

RetVal equals to 0, so function succeeds, but dvi (DLLVERSIONINFO structure)
doesn't have any members changed.

How can I get it passed?

If dvi is a strucure variable you have to do

Dim args As New Object() {dvi}
.... t.InvokeMember("DllGetVersion", ..., args)
dvi = CType(args(0), DLLVERSIONINFO)



Mattias
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Top