Solved

Using TLBINF32's InvokeHookArray?

Posted on 2000-05-05
13
511 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
SharePoint Admin?

Enable Your Employees To Focus On The Core With Intuitive Onscreen Guidance That is With You At The Moment of Need.

 

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 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



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

Creating Instructional Tutorials  

For Any Use & On Any Platform

Contextual Guidance at the moment of need helps your employees/users adopt software o& achieve even the most complex tasks instantly. Boost knowledge retention, software adoption & employee engagement with easy solution.

Question has a verified solution.

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

Introduction In a recent article (http://www.experts-exchange.com/A_7811-A-Better-Concatenate-Function.html) for the Excel community, I showed an improved version of the Excel Concatenate() function.  While writing that article I realized that no o…
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…
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…
This lesson covers basic error handling code in Microsoft Excel using VBA. This is the first lesson in a 3-part series that uses code to loop through an Excel spreadsheet in VBA and then fix errors, taking advantage of error handling code. This l…
Suggested Courses
Course of the Month11 days, 5 hours left to enroll

632 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