Still celebrating National IT Professionals Day with 3 months of free Premium Membership. Use Code ITDAY17

x
?
Solved

Using TLBINF32's InvokeHookArray?

Posted on 2000-05-05
13
Medium Priority
?
523 Views
Last Modified: 2008-02-20
I have a generic MTS Object Tester app (yes, this relates to a question I asked a couple of days ago) which needs to be able to call any method of an object without having preknowledge of the object's interface.

I am successfuly using the InvokeHookArray method from TLBINF32 with simple variable types, passed ByRef, like strings, integers, longs, etc. What I am having trouble with is passing a Variant array ByRef.

Some code I found from the TlbInf32 help files looks something like this:

Declare Sub CopyMemory Lib "kernel32" Alias "RtlMoveMemory" _
  (pDst As Any, pSrc As Any, ByVal ByteLen As Long)
Declare Function VarPtrArray Lib "msvbvm60.dll" Alias "VarPtr" _
  (Ptr() As Any) As Long

Dim obj As Object
Dim args() As Variant
Dim i As Integer
Dim iArr() As Integer
Dim vt As Integer
Dim InvokeID As Long
  'Call Foo(i As Integer, iArr() As Integer)
  ReDim args(1)
  'Use this code only with variable sized arrays.
  args(0) = VarPtrArray(iArr)
  vt = VT_BYREF Or VT_ARRAY Or VT_I2
  CopyMemory args(0), vt, 2
  args(1) = VarPtr(i)
  vt = VT_BYREF Or VT_I2
  CopyMemory args(1), vt, 2
  TLI.InvokeHookArray obj, "Foo", INVOKE_FUNC, args

Like I said, this works fine for simple types, anybody have any ideas on how to use this to pass a variant array?
0
Comment
Question by:garymather
[X]
Welcome to Experts Exchange

Add your voice to the tech community where 5M+ people just like you are talking about what matters.

  • Help others & share knowledge
  • Earn cash & points
  • Learn & ask questions
  • 7
  • 6
13 Comments
 
LVL 28

Expert Comment

by:AzraSound
ID: 2781051
0
 

Author Comment

by:garymather
ID: 2781103
AzraSound,

Nope, the way they are using the InvokeHookArray here passes the variables ByVal, not ByRef. According to the TlbInf32 documentation, you have to manipulate the variable using RtlMoveMemory to add the VT_BYREF bit to the variables declaration, or words to that effect. The documentation states that if you fill the "reverse" array with simple VB code, the variables are passed ByVal. I want to pass them ByRef.
0
 
LVL 28

Expert Comment

by:AzraSound
ID: 2781129
what is happening when you apply the code sample provided from the tlbinf32 documentation?
0
VIDEO: THE CONCERTO CLOUD FOR HEALTHCARE

Modern healthcare requires a modern cloud. View this brief video to understand how the Concerto Cloud for Healthcare can help your organization.

 

Author Comment

by:garymather
ID: 2781209
I get an Automation Error.

Here's the code that I am using:


ReDim varReverse(UBound(varParameters)) As Variant

ReDim aryString(UBound(varParameters)) As String
ReDim aryVariant(UBound(varParameters)) As Variant

lm = UBound(varParameters)
ln = 0
For Each objParameter In objMember.Parameters

   Select Case objParameter.VarTypeInfo.VarType
      Case VT_BSTR
         aryString(ln) = varParameters(ln)
         lngByteLen = Len(aryString(ln))
         varReverse(lm) = VarPtr(aryString(ln))
      Case VT_VARIANT
         aryVariant(ln) = varParameters(ln)
         lngByteLen = GetLengthInBytes(aryVariant(ln))
         varReverse(lm) = VarPtr(aryVariant(ln))
   End Select

   intVarType = VT_BYREF Or objParameter.VarTypeInfo.VarType
   If IsArray(varParameters(ln) Then
      intVarType = intVarType Or VT_ARRAY
   End If
   Call CopyMemory(varReverse(lm), intVarType, lngByteLen)

   lm = lm - 1
   ln = ln + 1
Next

varReturn = TLI.InvokeHookArray(objMTS, objItem.MemberId, INVOKE_FUNC, varReverse)

The GetLengthInBytes simple get the length of each of the elements in the array.

0
 
LVL 28

Expert Comment

by:AzraSound
ID: 2781245
what sort of debugging have you tried?  perhaps place a msgbox after each call to CopyMemory to see if, in fact, the proper values are being copied to it
0
 

Author Comment

by:garymather
ID: 2781290
I've single stepped it and checked all the vars. When I check the varReverse(lm) for the Variant array after the CopyMemory, I get :
"VB6.EXE Application Error
The instruction at "0x0fc03042" referenced memory at "0x0e0001d". The memory could not be "read".
0
 
LVL 28

Expert Comment

by:AzraSound
ID: 2781391
try foregoing the VarPtr step and leave the element of that array empty and then call copymemory.  see if the data is transferred.  if that makes no difference, try passing the second parameter ByVal

CopyMemory varReverse(lm), ByVal intVarType, lngByteLen





   
0
 

Author Comment

by:garymather
ID: 2781420
Nope, both of these generate the same VB6.EXE Application error....
0
 
LVL 28

Expert Comment

by:AzraSound
ID: 2781522
i apologize for not being more than just another debugging tool...i have been unable to find a direct answer to this problem anywhere.

question:
this array is declared as variant and is then filled with pointer values of another array yes?  we then determine the number of bytes in this array.  as a string it is the length of the string since characters are 1 byte values.  however when we perform copymemory we are telling it to copy lngByteLen bytes from the source to our destination. our source is just an integer though.  i think perhaps this could be part of the problem.

0
 

Author Comment

by:garymather
ID: 2781638
This was my initial thought. It looked confusing that the pSrc was an integer and not a pointer. But the fact remains that this method works perfectly when you are working with simple data types such as String, Integer etc. I wrote a simple MTS object that had a number of functions that took only one parameter, eg. TestFunc(aString As String) etc, In these functions I was able to manipulate the variable that was passed ByRef and the results of this manipulation were visible from the client.

I have searched numerous sites on the web but to no avail. This is my last resort. I even tried passing the variant array ByVal and other simple variables that I wanted to manipulate ByRef, but this fails. It seems it wants them all passed ByRef or all passed ByVal, no mixture of the two.
0
 
LVL 28

Accepted Solution

by:
AzraSound earned 800 total points
ID: 2781736
have you tried ByVal VarPtr(varReverse(lm)) and ByVal VarPtr(intVarType)??

possibly declare the varReverse array explicitly as a byte array and change it back later if you need to

maybe just pass 2& as the length to ensure its only reading 2 bytes



0
 

Author Comment

by:garymather
ID: 2781825
It never ceases to amaze me how stupid  one person can be! After reading your post it suddenly dawned on me that I was passing the number of bytes occupied by the parameter being passed, AND NOT THE NUMBER OF BYTES OCCUPIED BY AN INTEGER (intVarType) WHICH IS 2!!!!!!!!

So the final call is Call CopyMemory(varReverse(lm), intVarType, 2) and it works perfectly!

Thanks, you deserve the points if for nothing other than highlighting the error of my ways!
0
 
LVL 28

Expert Comment

by:AzraSound
ID: 2781840
i cant tell you how many times i've stared at code where the error was the most ridiculous thing.  we both missed this one, it must be contagious. regardless, i'm glad its working for you now.  take care.
0

Featured Post

Technology Partners: We Want Your Opinion!

We value your feedback.

Take our survey and automatically be enter to win anyone of the following:
Yeti Cooler, Amazon eGift Card, and Movie eGift Card!

Question has a verified solution.

If you are experiencing a similar issue, please ask a related question

Have you ever wanted to restrict the users input in a textbox to numbers, and while doing that make sure that they can't 'cheat' by pasting in non-numeric text? Of course you can do that with code you write yourself but it's tedious and error-prone …
If you have ever used Microsoft Word then you know that it has a good spell checker and it may have occurred to you that the ability to check spelling might be a nice piece of functionality to add to certain applications of yours. Well the code that…
Get people started with the process of using Access VBA to control Outlook using automation, Microsoft Access can control other applications. An example is the ability to programmatically talk to Microsoft Outlook. Using automation, an Access applic…
Show developers how to use a criteria form to limit the data that appears on an Access report. It is a common requirement that users can specify the criteria for a report at runtime. The easiest way to accomplish this is using a criteria form that a…
Suggested Courses

671 members asked questions and received personalized solutions in the past 7 days.

Join the community of 500,000 technology professionals and ask your questions.

Join & Ask a Question