Using TLBINF32's InvokeHookArray?

Posted on 2000-05-05
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)
  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?
Question by:garymather
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
LVL 28

Expert Comment

ID: 2781051

Author Comment

ID: 2781103

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.
LVL 28

Expert Comment

ID: 2781129
what is happening when you apply the code sample provided from the tlbinf32 documentation?
PeopleSoft Has Never Been Easier

PeopleSoft Adoption Made Smooth & Simple!

On-The-Job Training Is made Intuitive & Easy With WalkMe's On-Screen Guidance Tool.  Claim Your Free WalkMe Account Now


Author Comment

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

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

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

LVL 28

Expert Comment

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

Author Comment

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".
LVL 28

Expert Comment

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


Author Comment

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

Expert Comment

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.

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.


Author Comment

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.
LVL 28

Accepted Solution

AzraSound earned 200 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


Author Comment

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!
LVL 28

Expert Comment

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.

Featured Post

Online Training Solution

Drastically shorten your training time with WalkMe's advanced online training solution that Guides your trainees to action. Forget about retraining and skyrocket knowledge retention rates.

Question has a verified solution.

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

Introduction While answering a recent question about filtering a custom class collection, I realized that this could be accomplished with very little code by using the ScriptControl (SC) library.  This article will introduce you to the SC library a…
When trying to find the cause of a problem in VBA or VB6 it's often valuable to know what procedures were executed prior to the error. You can use the Call Stack for that but it is often inadequate because it may show procedures you aren't intereste…
Get people started with the utilization of class modules. Class modules can be a powerful tool in Microsoft Access. They allow you to create self-contained objects that encapsulate functionality. They can easily hide the complexity of a process from…
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…

729 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