Solved

Using TLBINF32's InvokeHookArray?

Posted on 2000-05-05
13
481 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
  • 7
  • 6
13 Comments
 
LVL 28

Expert Comment

by:AzraSound
Comment Utility
0
 

Author Comment

by:garymather
Comment Utility
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
Comment Utility
what is happening when you apply the code sample provided from the tlbinf32 documentation?
0
 

Author Comment

by:garymather
Comment Utility
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
Comment Utility
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
Comment Utility
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
Enabling OSINT in Activity Based Intelligence

Activity based intelligence (ABI) requires access to all available sources of data. Recorded Future allows analysts to observe structured data on the open, deep, and dark web.

 
LVL 28

Expert Comment

by:AzraSound
Comment Utility
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
Comment Utility
Nope, both of these generate the same VB6.EXE Application error....
0
 
LVL 28

Expert Comment

by:AzraSound
Comment Utility
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
Comment Utility
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
Comment Utility
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
Comment Utility
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
Comment Utility
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

How to improve team productivity

Quip adds documents, spreadsheets, and tasklists to your Slack experience
- Elevate ideas to Quip docs
- Share Quip docs in Slack
- Get notified of changes to your docs
- Available on iOS/Android/Desktop/Web
- Online/Offline

Join & Write a Comment

Suggested Solutions

Title # Comments Views Activity
Share codes 68 114
Window placement 17 64
How to delete rows after an End (xl Down) without deleting header row? 3 57
Validating VB6 Function 19 49
I’ve seen a number of people looking for examples of how to access web services from VB6.  I’ve been using a test harness I built in VB6 (using many resources I found online) that I use for small projects to work out how to communicate with web serv…
Most everyone who has done any programming in VB6 knows that you can do something in code like Debug.Print MyVar and that when the program runs from the IDE, the value of MyVar will be displayed in the Immediate Window. Less well known is Debug.Asse…
As developers, we are not limited to the functions provided by the VBA language. In addition, we can call the functions that are part of the Windows operating system. These functions are part of the Windows API (Application Programming Interface). U…
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…

771 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

Need Help in Real-Time?

Connect with top rated Experts

9 Experts available now in Live!

Get 1:1 Help Now