-
Oct 25th, 2022, 09:14 AM
#1
[RESOLVED] VB6 COM/Code Object Method Name ---> vTable Entry Number
Ok, I think this one is possible too, but I'm not sure how to get there.
I'm just talking about VB6 code objects (Classes, Forms, UCs, PropPages, & DataReports).
And I'm only talking about Public methods.
I'm staring at some code by Wqweto seen here. That shows how to use IDispatch to go from a method's name to its Dispatch_identifier. However, it doesn't show us how to get from there to the vTable entry.
Any tips on how to make this step would be greatly appreciated.
------------
Another idea I've got is to just get a complete list of Public methods of the object, in vTable order. From there, it'd be pretty easy. Maybe a function something like the following:
Code:
Option Explicit
Private Declare Function CLSIDFromString Lib "ole32" (ByVal lpsz As Any, pclsid As Any) As Long
Private Declare Function vbaCheckType Lib "msvbvm60" Alias "__vbaCheckType" (ByVal pObj As Any, ByRef pIID As Any) As Boolean
Public Function List_Of_Public_Vb6_Com_Methods(o As Object) As String()
If Not ObjectIsVb6ComCodeModule(o) Then
List_Of_Public_Vb6_Com_Methods = Split(vbNullString) ' 0 to -1 array.
Exit Function
End If
' Somehow call IDispatch::GetIDsOfNames and get the method list.
' And hopefully in vTable order.
' ??????????????
End Function
Private Function ObjectIsVb6ComCodeModule(o As IUnknown) As Boolean
Const AreYouABasicInstance As String = "{0B6C9465-D082-11CF-8B4F-00A0C90F2704}"
Dim aGUID(3&) As Long
CLSIDFromString StrPtr(AreYouABasicInstance), aGUID(0&)
ObjectIsVb6ComCodeModule = vbaCheckType(o, aGUID(0&))
End Function
Get/Let/Set methods (including Public variables) are a bit of a problem, but I don't really care about those. Maybe they can just be listed twice, without specifying whether they're Get or Let/Set.
Again, any tips on how to do this would be greatly appreciated.
------------
I'm trying my best to not be a "cargo culter". I'm just not sure where to get started with this, but I'll be searching while I'm waiting on tips.
Any software I post in these forums written by me is provided “AS IS” without warranty of any kind, expressed or implied, and permission is hereby granted, free of charge and without restriction, to any person obtaining a copy. Please understand that I’ve been programming since the mid-1970s and still have some of that code. My contemporary VB6 project is approaching 1,000 modules. In addition, I have a “VB6 random code folder” that is overflowing. I’ve been at this long enough to truly not know with absolute certainty from whence every single line of my code has come, with much of it coming from programmers under my employ who signed intellectual property transfers. I have not deliberately attempted to remove any licenses and/or attributions from any software. If someone finds that I have inadvertently done so, I sincerely apologize, and, upon notice and reasonable proof, will re-attach those licenses and/or attributions. To all, peace and happiness.
-
Oct 25th, 2022, 10:33 AM
#2
Re: VB6 COM/Code Object Method Name ---> vTable Entry Number
Dang, I thought LaVolpe had done it in this thread.
But he closed the thread with the following:
Believe I'm going to abandon this train of logic/thought ... Maybe I'll post what I've got (working example) and let others continue down that path if they choose.
But he didn't post it. Boo.
Any software I post in these forums written by me is provided “AS IS” without warranty of any kind, expressed or implied, and permission is hereby granted, free of charge and without restriction, to any person obtaining a copy. Please understand that I’ve been programming since the mid-1970s and still have some of that code. My contemporary VB6 project is approaching 1,000 modules. In addition, I have a “VB6 random code folder” that is overflowing. I’ve been at this long enough to truly not know with absolute certainty from whence every single line of my code has come, with much of it coming from programmers under my employ who signed intellectual property transfers. I have not deliberately attempted to remove any licenses and/or attributions from any software. If someone finds that I have inadvertently done so, I sincerely apologize, and, upon notice and reasonable proof, will re-attach those licenses and/or attributions. To all, peace and happiness.
-
Oct 25th, 2022, 12:47 PM
#3
Re: VB6 COM/Code Object Method Name ---> vTable Entry Number
Hmmm, I'm poking around at the tObjectInfo and tObject structures, but I'm not making any progress.
In tObjectInfo, there's an item named aProcTable (aka, aMethodTable). In tObject, there's an item named aProcNamesArray (aka, aMethodNameTable). I've peeked at both of these, and I can't make heads-or-tails of any of it.
Here's code I'm using to peek at these things:
Code:
Option Explicit
'
Private Type tObjectInfo
Flag1 As Integer ' 0x00
ObjectIndex As Integer ' 0x02
aObjectTable As Long ' 0x04
Null1 As Long ' 0x08
aSmallRecord As Long ' 0x0C (aObjectDescriptor) when it is a module this value is -1 [better name?]
Const1 As Long ' 0x10
Null2 As Long ' 0x14
aObject As Long ' 0x18 (aObjectHeader)
RunTimeLoaded As Long ' 0x1C (aObjectData)
NumberOfProcs As Long ' 0x20 (iMethodCount, maybe only Integer)
aProcTable As Long ' 0x24 (aMethodTable) Pointer to an array of method pointers
iConstantsCount As Integer '0x28 (40d) Number of Constants
iMaxConstants As Integer '0x2A (42d) Maximum Constants to allocate.
Flag5 As Long ' 0x2C
Flag6 As Integer ' 0x30
Flag7 As Integer ' 0x32
aConstantPool As Long ' 0x34 (aConstantTable)
' 0x38 <-- Structure Size
'the rest is optional items[OptionalObjectInfo]
'
dwObjectGuiGuids As Long ' 0x38 / 0x0 Number of ObjectGUI GUIDs (2 for Designer)
lpObjectCLSID As Long ' 0x3C / 0x4 Pointer to object CLSID
dwNull As Long ' 0x40 / 0x8
lpGuidObjectGUITable As Long ' 0x44 / 0xC Pointer to pointers of guidObjectGUI
dwObjectDefaultIIDCount As Long ' 0x48 / 0x10 Number of DefaultIIDs
lpObjectEventsIIDTable As Long ' 0x4C / 0x14 Pointer to pointers of EventsIID
dwObjectEventsIIDCount As Long ' 0x50 / 0x18 Number of EventsIID
lpObjectDefaultIIDTable As Long ' 0x54 / 0x1C Pointer to pointers of DefaultIID
dwControlCount As Long ' 0x58 / 0x20 dwControlCount Number of Controls in array below.
lpControls As Long ' 0x5C / 0x24 lpControls Pointer to Controls Array.
wMethodLinkCount As Integer ' 0x60 / 0x28 wMethodLinkCount Number of Method Links
wPCodeCount As Integer ' 0x62 / 0x2A wPCodeCount Number of P-Codes used by this Object.
bWInitializeEvent As Integer ' 0x64 / 0x2C bWInitializeEvent Offset to Initialize Event from Event Table.
bWTerminateEvent As Integer ' 0x66 / 0x2E bWTerminateEvent Offset to Terminate Event in Event Table.
lpMethodLinkTable As Long ' 0x68 / 0x30 lpMethodLinkTable Pointer to pointers of MethodLink
lpBasicClassObject As Long ' 0x6C / 0x34 lpBasicClassObject Pointer to in-memory Class Objects.
dwNull3 As Long ' 0x70 / 0x38 dwNull3 Unused.
lpIdeData As Long ' 0x74 / 0x3C lpIdeData Only valid in IDE.
' 0x78 / 0x40 <-- Structure Size
End Type
Private Type tObject
aObjectInfo As Long ' 0x00
Const1 As Long ' 0x04
aPublicBytes As Long ' 0x08 (08d) Pointer to Public Variable Size integers
aStaticBytes As Long ' 0x0C (12d) Pointer to Static Variables Struct
aModulePublic As Long ' 0x10 (16d) Memory Pointer to Public Variables
aModuleStatic As Long ' 0x14 (20d) Pointer to Static Variables
aObjectName As Long ' 0x18 NTS (aNTSObjectName)
ProcCount As Long ' 0x1C events, funcs, subs (lMethodCount, maybe only Integer)
aProcNamesArray As Long ' 0x20 when non-zero (aMethodNameTable) Pointer to an array of function addresses
oStaticVars As Long ' 0x24 (36d) Offset to Static Vars from aModuleStatic
ObjectType As Long ' 0x28
Null3 As Long ' 0x2C
' 0x30 <-- Structure Size
End Type
Private Declare Function GetMem4 Lib "msvbvm60" (ByRef Source As Any, ByRef Dest As Any) As Long
Private Declare Function GetMem2 Lib "msvbvm60" (ByRef Source As Any, ByRef Dest As Any) As Long
Private Declare Sub CopyMemory Lib "kernel32" Alias "RtlMoveMemory" (ByRef Destination As Any, ByRef Source As Any, ByVal Length As Long)
Public Sub TestProc()
'
End Sub
Private Sub Form_Load()
Dim pVtable As Long: GetMem4 ByVal ObjPtr(Me), pVtable
Dim ptObjectInfo As Long: GetMem4 ByVal pVtable - 4&, ptObjectInfo
Dim uObjectInfo As tObjectInfo: CopyMemory uObjectInfo, ByVal ptObjectInfo, LenB(uObjectInfo)
Dim uObject As tObject: CopyMemory uObject, ByVal uObjectInfo.aObject, LenB(uObject)
'
' Report certain values:
DebugPrint "Test1: " & CStr(uObjectInfo.NumberOfProcs)
DebugPrint "Test2: " & CStr(uObject.ProcCount)
DebugPrint "aProcTable : " & CStr(uObjectInfo.aProcTable)
DebugPrint "aProcNamesArray: " & CStr(uObject.aProcNamesArray)
Dim bb(999) As Byte
'CopyMemory bb(0), ByVal uObjectInfo.aProcTable, 1000
CopyMemory bb(0), ByVal uObject.aProcNamesArray, 1000
Dim i As Long
For i = LBound(bb) To UBound(bb)
DebugPrint bb(i) & " " & Chr(bb(i))
Next
Unload Me
End Sub
'Dim s As String
's = Space$(500)
'CopyMemory ByVal StrPtr(s), ByVal uObjectinfo.aProcTable, LenB(s)
'CopyMemory ByVal StrPtr(s), ByVal uObject.aProcNamesArray, LenB(s)
'Dim i As Long
'For i = 1 To Len(s)
' DebugPrint "s: " & AscW(Mid$(s, i, 1)) & " " & Mid$(s, i, 1)
'Next
I've tried snooping as both Bytes and Unicode characters, but nothing seems to make sense.
Also, I'm using my persistent Debug window, so you'll have to change the "DebugPrint" to something else to see the results if you wish to test. But they're just nonsense in all cases.
Any software I post in these forums written by me is provided “AS IS” without warranty of any kind, expressed or implied, and permission is hereby granted, free of charge and without restriction, to any person obtaining a copy. Please understand that I’ve been programming since the mid-1970s and still have some of that code. My contemporary VB6 project is approaching 1,000 modules. In addition, I have a “VB6 random code folder” that is overflowing. I’ve been at this long enough to truly not know with absolute certainty from whence every single line of my code has come, with much of it coming from programmers under my employ who signed intellectual property transfers. I have not deliberately attempted to remove any licenses and/or attributions from any software. If someone finds that I have inadvertently done so, I sincerely apologize, and, upon notice and reasonable proof, will re-attach those licenses and/or attributions. To all, peace and happiness.
-
Oct 25th, 2022, 02:05 PM
#4
Re: VB6 COM/Code Object Method Name ---> vTable Entry Number
Code:
Option Explicit
Option Base 0
Public Enum PTR
[_]
End Enum
Private Declare Function GetMem1 Lib "msvbvm60" ( _
ByRef Source As Any, _
ByRef Dest As Any) As Long
Private Declare Function GetMem4 Lib "msvbvm60" ( _
ByRef Source As Any, _
ByRef Dest As Any) As Long
Private Declare Function GetMemPtr Lib "msvbvm60" Alias "GetMem4" ( _
ByRef Source As Any, _
ByRef Dest As Any) As Long
Private Declare Function GetMem2 Lib "msvbvm60" ( _
ByRef Source As Any, _
ByRef Dest As Any) As Long
Private Declare Function lstrlenA Lib "kernel32" ( _
ByRef lpString As Any) As Long
Private Declare Function SysAllocStringByteLen Lib "oleaut32" ( _
ByRef psz As Any, _
ByVal lSize As Long) As String
' // Get list of VB6 object methods
Public Property Get ListOfMethods( _
ByVal cObj As Object) As String()
Dim sRet() As String
Dim lIndex As Long
Dim lCount As Long
Dim pObjInfo As PTR
Dim pPubDesc As PTR
Dim pPrivDesc As PTR
Dim pMembers As PTR
Dim pMethDesc As PTR
Dim pVTbl As PTR
Dim lMethods As Long
Dim pNames As PTR
Dim pName As PTR
Dim lMethOffset As Long
Dim lPropCount As Long
Dim lFlags As Long
GetMemPtr ByVal ObjPtr(cObj), pVTbl
GetMemPtr ByVal pVTbl - 4, pObjInfo
GetMemPtr ByVal pObjInfo + &H18, pPubDesc
GetMemPtr ByVal pObjInfo + &HC, pPrivDesc
GetMemPtr ByVal pPubDesc + &H20, pNames
If pPrivDesc = 0 Then
Exit Property
End If
GetMemPtr ByVal pPrivDesc + &H18, pMembers
GetMem2 ByVal pPubDesc + &H1C, lMethods
If lMethods = 0 Then
Exit Property
End If
For lIndex = 0 To lMethods - 1
GetMemPtr ByVal pMembers, pMethDesc
If pMethDesc Then
GetMem2 ByVal pMethDesc + 2, lMethOffset
If lMethOffset And 1 Then
lMethOffset = lMethOffset And -2
GetMemPtr ByVal pNames + lIndex * Len(pName), pName
If lCount Then
If lCount > UBound(sRet) Then
ReDim Preserve sRet(lCount + 10)
End If
Else
ReDim sRet(9)
End If
sRet(lCount) = SysAllocStringByteLen(ByVal pName, lstrlenA(ByVal pName))
lCount = lCount + 1
End If
End If
pMembers = pMembers + 4
Next
GetMem2 ByVal pPrivDesc + &H10, lPropCount
GetMemPtr ByVal pPrivDesc + &H20, pMembers
For lIndex = 0 To lPropCount - 1
GetMemPtr ByVal pMembers, pMethDesc
If pMethDesc Then
GetMem2 ByVal pMethDesc + &H10, lFlags
If lFlags And 2 Then
GetMemPtr ByVal pMethDesc, pName
GetMem2 ByVal pMethDesc + &H12, lMethOffset
If lCount Then
If lCount > UBound(sRet) Then
ReDim Preserve sRet(lCount + 10)
End If
Else
ReDim sRet(9)
End If
sRet(lCount) = SysAllocStringByteLen(ByVal pName, lstrlenA(ByVal pName))
lCount = lCount + 1
End If
End If
pMembers = pMembers + 4
Next
If lCount Then
ReDim Preserve sRet(lCount - 1)
End If
ListOfMethods = sRet
End Property
Last edited by The trick; Oct 26th, 2022 at 11:49 AM.
-
Oct 25th, 2022, 02:25 PM
#5
Re: VB6 COM/Code Object Method Name ---> vTable Entry Number
Trick, that's crazy cool.
I tested both in IDE and compiled, and it works flawlessly.
THANK YOU!!!
(Now I've got to study it and see if I can understand it.)
Any software I post in these forums written by me is provided “AS IS” without warranty of any kind, expressed or implied, and permission is hereby granted, free of charge and without restriction, to any person obtaining a copy. Please understand that I’ve been programming since the mid-1970s and still have some of that code. My contemporary VB6 project is approaching 1,000 modules. In addition, I have a “VB6 random code folder” that is overflowing. I’ve been at this long enough to truly not know with absolute certainty from whence every single line of my code has come, with much of it coming from programmers under my employ who signed intellectual property transfers. I have not deliberately attempted to remove any licenses and/or attributions from any software. If someone finds that I have inadvertently done so, I sincerely apologize, and, upon notice and reasonable proof, will re-attach those licenses and/or attributions. To all, peace and happiness.
-
Oct 25th, 2022, 03:50 PM
#6
Re: VB6 COM/Code Object Method Name ---> vTable Entry Number
Hi Trick,
Ok, I'm slowly getting my head around this.
There are a couple of bugs in the "Properties" loop though (the second loop). The "Methods/Procedures" loop seems to be working fine.
1. It's picking up both Public and Private Properties.
2. If there is more than one Property (module level variable), it's reporting the same name (the first one) for all of them.
-----------
I could possibly fix the second one. But I'm not sure how to fix the first one. I tried doing it the same way as the Methods/Procedures (GetMem2 ByVal pMethDesc + 2, lMethOffset: If lMethOffset And 1 Then ...) but that didn't work. So I just don't know where the Public/Private flag is for these Properties.
I'll work on fixing the first one (the names of the Properties).
Again, a HUGE thanks for this.
Any software I post in these forums written by me is provided “AS IS” without warranty of any kind, expressed or implied, and permission is hereby granted, free of charge and without restriction, to any person obtaining a copy. Please understand that I’ve been programming since the mid-1970s and still have some of that code. My contemporary VB6 project is approaching 1,000 modules. In addition, I have a “VB6 random code folder” that is overflowing. I’ve been at this long enough to truly not know with absolute certainty from whence every single line of my code has come, with much of it coming from programmers under my employ who signed intellectual property transfers. I have not deliberately attempted to remove any licenses and/or attributions from any software. If someone finds that I have inadvertently done so, I sincerely apologize, and, upon notice and reasonable proof, will re-attach those licenses and/or attributions. To all, peace and happiness.
-
Oct 25th, 2022, 04:04 PM
#7
Re: VB6 COM/Code Object Method Name ---> vTable Entry Number
Ahhh, the same fix fixed both bugs:
In Trick's second loop, just after the For lIndex = 0 To lPropCount - 1, the following line:
Code:
GetMemPtr ByVal pMembers, pMethDesc
... needs to be changed to ...
Code:
GetMem4 ByVal pMembers + lIndex * 4&, pMethDesc
Any software I post in these forums written by me is provided “AS IS” without warranty of any kind, expressed or implied, and permission is hereby granted, free of charge and without restriction, to any person obtaining a copy. Please understand that I’ve been programming since the mid-1970s and still have some of that code. My contemporary VB6 project is approaching 1,000 modules. In addition, I have a “VB6 random code folder” that is overflowing. I’ve been at this long enough to truly not know with absolute certainty from whence every single line of my code has come, with much of it coming from programmers under my employ who signed intellectual property transfers. I have not deliberately attempted to remove any licenses and/or attributions from any software. If someone finds that I have inadvertently done so, I sincerely apologize, and, upon notice and reasonable proof, will re-attach those licenses and/or attributions. To all, peace and happiness.
-
Oct 25th, 2022, 04:19 PM
#8
Re: VB6 COM/Code Object Method Name ---> vTable Entry Number
pMethDesc + &H12, lMethOffset do you have a description of this field vtable offset of the property ?
+&h14 i is the data offset for storage (ie Objptr()+[pMethDesc + &h14]) i believe
also did you have a breakdown of the flags meaning for following:
pMethDesc + &H10, lFlags
I have seen the pMethDesc + 2, lMethOffset bit 1 flag set but not sure of its meaning either, its weird they stuffed a bit flag in there like that
-
Oct 25th, 2022, 04:46 PM
#9
Re: VB6 COM/Code Object Method Name ---> vTable Entry Number
 Originally Posted by dz32
pMethDesc + &H12, lMethOffset do you have a description of this field vtable offset of the property ?
+&h14 i is the data offset for storage (ie Objptr()+[pMethDesc + &h14]) i believe
also did you have a breakdown of the flags meaning for following:
pMethDesc + &H10, lFlags
I have seen the pMethDesc + 2, lMethOffset bit 1 flag set but not sure of its meaning either, its weird they stuffed a bit flag in there like that
Hold on. Give me a few minutes. I'm reworking the whole thing with as many comments as I can figure out.
Any software I post in these forums written by me is provided “AS IS” without warranty of any kind, expressed or implied, and permission is hereby granted, free of charge and without restriction, to any person obtaining a copy. Please understand that I’ve been programming since the mid-1970s and still have some of that code. My contemporary VB6 project is approaching 1,000 modules. In addition, I have a “VB6 random code folder” that is overflowing. I’ve been at this long enough to truly not know with absolute certainty from whence every single line of my code has come, with much of it coming from programmers under my employ who signed intellectual property transfers. I have not deliberately attempted to remove any licenses and/or attributions from any software. If someone finds that I have inadvertently done so, I sincerely apologize, and, upon notice and reasonable proof, will re-attach those licenses and/or attributions. To all, peace and happiness.
-
Oct 25th, 2022, 05:04 PM
#10
Re: VB6 COM/Code Object Method Name ---> vTable Entry Number
Ok, here's my current effort to understand this thing:
Code:
Option Explicit
Private Declare Function GetMem1 Lib "msvbvm60" (ByRef Source As Any, ByRef Dest As Any) As Long
Private Declare Function GetMem4 Lib "msvbvm60" (ByRef Source As Any, ByRef Dest As Any) As Long
Private Declare Function GetMem2 Lib "msvbvm60" (ByRef Source As Any, ByRef Dest As Any) As Long
Private Declare Function lstrlenA Lib "kernel32" (ByRef lpString As Any) As Long
Private Declare Function SysAllocStringByteLen Lib "oleaut32" (ByRef psz As Any, ByVal lSize As Long) As String
Private Declare Function CLSIDFromString Lib "ole32" (ByVal lpsz As Any, pclsid As Any) As Long
Private Declare Function vbaCheckType Lib "msvbvm60" Alias "__vbaCheckType" (ByVal pObj As Any, ByRef pIID As Any) As Boolean
Private Sub Form_Load()
Dim sa() As String
sa = ListOfPublicVb6ComMembers(Me)
Dim i As Long
For i = LBound(sa) To UBound(sa)
MsgBox sa(i)
Next
Unload Me
End Sub
Public Function ListOfPublicVb6ComMembers(ByVal o As Object) As String()
' These should be returned in vTable order.
' So, after the offset for IUnknown & IDispatch as well as the intrinsic members,
' This can tell us a vTable offset for these members.
' It's zero-based so don't forget that when searching the returned string array.
'
ListOfPublicVb6ComMembers = Split(vbNullString) ' Just a default return.
If Not ObjectIsVb6ComCodeModule(o) Then Exit Function ' Make sure we're dealing with a VB6 COM-code object.
'
Dim pVTbl As Long: GetMem4 ByVal ObjPtr(o), pVTbl ' Pointer to vTable.
Dim pObjInfo As Long: GetMem4 ByVal pVTbl - 4&, pObjInfo ' Pointer to tObjectInfo structure.
Dim pPubDesc As Long: GetMem4 ByVal pObjInfo + &H18&, pPubDesc ' tObjectInfo.aObject which points to tObject structure.
Dim pPrivDesc As Long: GetMem4 ByVal pObjInfo + &HC&, pPrivDesc ' tObjectInfo.lpPrivateObject which points to tPrivateObj structure.
'
If pPrivDesc = 0& Then Exit Function ' Just a double-check.
'
Dim sRet() As String: sRet = Split(vbNullString) ' Start with 0 to -1 array.
Dim lIndex As Long
Dim lCount As Long
Dim pName As Long
'
' Gather the Public Variables at the top of the module.
Dim lFlags As Long
Dim pPropDesc As Long
Dim lPropsCnt As Long: GetMem2 ByVal pPrivDesc + &H10&, lPropsCnt ' tPrivateObj.cntPublicVars value.
Dim pPropsPtr As Long: GetMem4 ByVal pPrivDesc + &H20&, pPropsPtr ' tPrivateObj.lpPublicVars which points to array of pointers to structure with property info (tPropInfo).
'
For lIndex = 0& To lPropsCnt - 1&
GetMem4 ByVal pPropsPtr + lIndex * 4&, pPropDesc ' Get tPropInfo for property.
If pPropDesc Then ' Zero if not "Public".
GetMem2 ByVal pPropDesc + &H10&, lFlags ' tPropInfo.lFlags.
If lFlags And 2& Then ' Not sure why this is tested (maybe double-check for "Public")???
GetMem4 ByVal pPropDesc, pName ' tPropInfo.pName, pointer to property's name.
If (lCount + 1&) > UBound(sRet) Then ReDim Preserve sRet(lCount + 100&)
' Return TWO entries so we can keep the vTable count correct.
sRet(lCount) = "Get var " & SysAllocStringByteLen(ByVal pName, lstrlenA(ByVal pName))
lCount = lCount + 1&
sRet(lCount) = "Let/Set var " & SysAllocStringByteLen(ByVal pName, lstrlenA(ByVal pName))
lCount = lCount + 1&
End If
End If
Next
'
' Gather the Public Properties within the module.
Dim lMethOffset As Long
Dim pMethDesc As Long
Dim lMethodsCnt As Long: GetMem2 ByVal pPubDesc + &H1C&, lMethodsCnt ' tObject.ProcCount value.
Dim pNames As Long: GetMem4 ByVal pPubDesc + &H20&, pNames ' tObject.aProcNamesArray which points to an array of name pointers.
Dim pMethodsPtr As Long: GetMem4 ByVal pPrivDesc + &H18&, pMethodsPtr ' tPrivateObj.lpFuncTypeInfo which points to an array of pointers.
'
For lIndex = 0& To lMethodsCnt - 1&
GetMem4 ByVal pMethodsPtr + lIndex * 4&, pMethDesc ' From the array, getting a pointer to a method structure (tMethInfo).
If pMethDesc Then ' Not sure if this ever returns zero, maybe for "Private" methods?
GetMem2 ByVal pMethDesc + 2&, lMethOffset ' A flag out of tMethInfo structure.
If lMethOffset And 1& Then ' "Public" bit from flag.
GetMem4 ByVal pNames + lIndex * 4&, pName ' Dig pointer to method name from array of name pointers.
If lCount > UBound(sRet) Then ReDim Preserve sRet(lCount + 100&)
sRet(lCount) = SysAllocStringByteLen(ByVal pName, lstrlenA(ByVal pName))
lCount = lCount + 1& ' This time, only count once, as Get & Let/Set appear separately for methods.
End If
End If
Next
'
' Return what we found, or 0 to -1 array.
If lCount Then
ReDim Preserve sRet(lCount - 1&)
ListOfPublicVb6ComMembers = sRet
End If
End Function
Public Function ObjectIsVb6ComCodeModule(o As IUnknown) As Boolean
Const AreYouABasicInstance As String = "{0B6C9465-D082-11CF-8B4F-00A0C90F2704}"
Dim aGUID(3&) As Long
CLSIDFromString StrPtr(AreYouABasicInstance), aGUID(0&)
ObjectIsVb6ComCodeModule = vbaCheckType(o, aGUID(0&))
End Function
What'd I do:
- Renamed the function.
- Fixed the bug in the "properties" loop.
- Reversed the "methods" loop and the "properties" loop so they'd return in vTable order.
- Moved the Dim declarations around to be closer to where they're used.
- Made a separate set of variables for the "properties" loop and the "methods" loop.
- Documented as much as I could figure out.
- Just made longer lines. I've got a very wide monitor, so I like the long lines. I also "pretend" I've got declare-and-assign (like C/C++) and put it all on the same line.
- Added TWO entries for the properties (i.e., Public variables). I also prepended "Get var " and "Let/Set var " to these.
What I still don't understand:
- I've got no documentation for the tPropInfo structure. It's clearly a structure array for the properties. In fact, I just made up that name. pName and lFlags are coming out of it.
- I've got no documentation for the tPropInfo.lFlags or its bits. In fact, it seems to run the same regardless of whether that flag is checked or not.
- I've got no documentation for the tMethInfo structure. Again, it's clearly a structure array for the methods. Again, I just made up the structure name. lMethOffset is coming out of it, which is really some bit flags.
- I've got no documentation for the tMethInfo.lMethOffset flags or its bits.
Maybe The Trick will notice this and provide us some documentation for these structures. I'm glad it works though.
Last edited by Elroy; Oct 25th, 2022 at 05:35 PM.
Any software I post in these forums written by me is provided “AS IS” without warranty of any kind, expressed or implied, and permission is hereby granted, free of charge and without restriction, to any person obtaining a copy. Please understand that I’ve been programming since the mid-1970s and still have some of that code. My contemporary VB6 project is approaching 1,000 modules. In addition, I have a “VB6 random code folder” that is overflowing. I’ve been at this long enough to truly not know with absolute certainty from whence every single line of my code has come, with much of it coming from programmers under my employ who signed intellectual property transfers. I have not deliberately attempted to remove any licenses and/or attributions from any software. If someone finds that I have inadvertently done so, I sincerely apologize, and, upon notice and reasonable proof, will re-attach those licenses and/or attributions. To all, peace and happiness.
-
Oct 25th, 2022, 05:20 PM
#11
Re: VB6 COM/Code Object Method Name ---> vTable Entry Number
the following is my current understanding of these structs. dont have offsets added into my defs but vbdec will show them in its struct dumps
Code:
Private Type tPrivateObj
nul1 As Long
lpParentLink As Long
unk1 As Long
nul2 As Long
cntPublicVars As Integer
cntEvents As Integer
nul3 As Long
lpFuncTypeInfo As Long 'array of pubFuncTypeDesc pointers, nulls for private funcs with Object->ProcCount members
nul4 As Long
lpPublicVars As Long 'array of pubVarTypeDesc pointers with cntPublicVars members
lpEventsTypeInfo As Long 'array of pubEventTypeDesc pointers with cntEvents members
lpNull As Long
nul5 As Long
nul6 As Long
nul7 As Long
unk3 As Long
unk4 As Long
End Type
Private Type pubEventTypeDesc
argSize As Byte
isFunc As Byte
constFFFF As Long
nul1 As Long
nul2 As Integer
memberID As Long
lpAryArgNames As Long 'last array entry null
lpFuncDesc As Long
nul3 As Long
helpID As Long
unk1 As Byte 'always 1e for hResult?
End Type
Private Type pubFuncTypeDesc
argSize As Byte
flags As Byte
vOff As Integer
constFFFF As Integer
nul1 As Integer
optionalVals As Long
memberID As Long
lpAryArgNames As Long
lpFuncDesc As Long
nul3 As Long
helpID As Long
unk1 As Byte 'always 1e ?
End Type
Private Type pubVarTypeDesc
lpName As Long
nul1 As Long
nul2 As Long
index As Integer
unk1 As Byte
unk2 As Byte
unk3 As Integer
unk4 As Integer
varOffset As Long 'from objPtr for data store
End Type
Last edited by dz32; Oct 25th, 2022 at 05:28 PM.
-
Oct 25th, 2022, 05:26 PM
#12
Re: VB6 COM/Code Object Method Name ---> vTable Entry Number
 Originally Posted by dz32
the following is my current understanding of these structs.
Thanks. I like having that documentation.
Any software I post in these forums written by me is provided “AS IS” without warranty of any kind, expressed or implied, and permission is hereby granted, free of charge and without restriction, to any person obtaining a copy. Please understand that I’ve been programming since the mid-1970s and still have some of that code. My contemporary VB6 project is approaching 1,000 modules. In addition, I have a “VB6 random code folder” that is overflowing. I’ve been at this long enough to truly not know with absolute certainty from whence every single line of my code has come, with much of it coming from programmers under my employ who signed intellectual property transfers. I have not deliberately attempted to remove any licenses and/or attributions from any software. If someone finds that I have inadvertently done so, I sincerely apologize, and, upon notice and reasonable proof, will re-attach those licenses and/or attributions. To all, peace and happiness.
-
Oct 25th, 2022, 05:36 PM
#13
Re: VB6 COM/Code Object Method Name ---> vTable Entry Number
Using the above (code in post #10), the following can be used to determine the vTable entry. Please be sure to read the comments:
Code:
Public Function VtableEntryForPublicMethod(ByVal o As Object, ByVal sMethodName As String) As Long
' Returns the 1-based vTable entry offset for sMethodName.
' The IUnknown, IDispatch, and intrinsic vTable entries are NOT accounted for, and must be added.
' If a Get or Let/Set method is searched, the first one found will be returned (order in source code).
' There is no provision for returning "Property" (Public variables) vTable entries,
' but they will be correctly counted in the returned offset.
'
' If it can't be found, ZERO is returned.
'
Dim sa() As String
sa = ListOfPublicVb6ComMembers(o)
sMethodName = UCase$(sMethodName) ' Make sure we're case-insensitive, as VB6 is.
Dim i As Long
For i = LBound(sa) To UBound(sa)
If UCase$(sa(i)) = sMethodName Then
VtableEntryForPublicMethod = i + 1&
Exit Function
End If
Next
' If we fall out, it's not found so return 0.
End Function
So, unless there's something wrong that I haven't found, this one is resolved.
Just as an FYI, I've tested both IDE running and machine compiled, and it seems to all work fine.
Last edited by Elroy; Oct 25th, 2022 at 05:41 PM.
Any software I post in these forums written by me is provided “AS IS” without warranty of any kind, expressed or implied, and permission is hereby granted, free of charge and without restriction, to any person obtaining a copy. Please understand that I’ve been programming since the mid-1970s and still have some of that code. My contemporary VB6 project is approaching 1,000 modules. In addition, I have a “VB6 random code folder” that is overflowing. I’ve been at this long enough to truly not know with absolute certainty from whence every single line of my code has come, with much of it coming from programmers under my employ who signed intellectual property transfers. I have not deliberately attempted to remove any licenses and/or attributions from any software. If someone finds that I have inadvertently done so, I sincerely apologize, and, upon notice and reasonable proof, will re-attach those licenses and/or attributions. To all, peace and happiness.
-
Oct 25th, 2022, 06:14 PM
#14
Re: [RESOLVED] VB6 COM/Code Object Method Name ---> vTable Entry Number
I would use the pubFuncTypeDesc.voff value over a self calculated value for vtable offset
This is what trick had and -2 because they set bit 1 of that field as a flag for some reason
All public vars will generate a get/let pair, and some will generate a get/let/set depending on variable type
Variant and object data types should have 3 entries per. There is a way to check the type of the var that’s part of tomorrows article.
Last edited by dz32; Oct 25th, 2022 at 06:18 PM.
-
Oct 25th, 2022, 06:36 PM
#15
Re: [RESOLVED] VB6 COM/Code Object Method Name ---> vTable Entry Number
 Originally Posted by dz32
I would use the pubFuncTypeDesc.voff value over a self calculated value for vtable offset
This is what trick had and -2 because they set bit 1 of that field as a flag for some reason
All public vars will generate a get/let pair, and some will generate a get/let/set depending on variable type
Variant and object data types should have 3 entries per. There is a way to check the type of the var that’s part of tomorrows article.
Oh WOW, I didn't think about there actually being a stored value for the offset. I'll definitely look into it.
Any software I post in these forums written by me is provided “AS IS” without warranty of any kind, expressed or implied, and permission is hereby granted, free of charge and without restriction, to any person obtaining a copy. Please understand that I’ve been programming since the mid-1970s and still have some of that code. My contemporary VB6 project is approaching 1,000 modules. In addition, I have a “VB6 random code folder” that is overflowing. I’ve been at this long enough to truly not know with absolute certainty from whence every single line of my code has come, with much of it coming from programmers under my employ who signed intellectual property transfers. I have not deliberately attempted to remove any licenses and/or attributions from any software. If someone finds that I have inadvertently done so, I sincerely apologize, and, upon notice and reasonable proof, will re-attach those licenses and/or attributions. To all, peace and happiness.
-
Oct 25th, 2022, 06:49 PM
#16
Re: [RESOLVED] VB6 COM/Code Object Method Name ---> vTable Entry Number
what I have as pubVarTypeDesc.unk4 trick correctly noticed is the vtable offset for the first property get of that particular public variable.
I do not see anything in the structure that lists explicitly if it has an additional set property with it. (although you can figure it out looking at the variable type.)
one of my dumps for the following:
Code:
Public a As Long
Public myPublicVar As Scripting.FileSystemObject
Property Let myManualProp(d As Date, i As Long)
Public VarTypes:
VA Off Name = Value
40214C 000 lpName = 402394 -> Public a As Long (reconstructed prototype)
402150 004 nul1 = 0
402154 008 nul2 = 0
402158 00C index = 0
40215A 00E unk1 = 3
40215B 00F unk2 = 40
40215C 010 unk3 = 2
40215E 012 unk4 = 1C <-- first vtable offset for this property get
402160 014 varOffset = 3C
VA Off Name = Value
402168 000 lpName = 402398 -> Public myPublicVar As IFileSystem3 (reconstructed prototype)
40216C 004 nul1 = 0
402170 008 nul2 = 0
402174 00C index = 1
402176 00E unk1 = 3
402177 00F unk2 = 40
402178 010 unk3 = 2
40217A 012 unk4 = 24 <-- first vtable offset for this property get (1c/20 taken by get/let Public a As Long)
40217C 014 varOffset = 40
Public Funcs:
Public Property Let myManualProp(d As Date, i As Long) (reconstructed prototype)
VA Off Name = Value
40225C 000 argSize = A (2 args)
40225D 001 flags = 0
40225E 002 vOff = 31 <-- vtable offset +1 for this property (24/28/2c taken by get/let/set myPublicVar)
402260 004 constFFFF = FFFF
402262 006 nul1 = 0
402264 008 optionalVals = 0
402268 00C memberID = 68030001
40226C 010 lpAryArgNames = 4020FC
402270 014 lpFuncDesc = 0
402274 018 nul3 = 0
402278 01C helpID = 0
40227C 020 unk1 = 1E
TypeBytes: 2C 28 0
and the autogenerated native stubs for those get/let/sets where you can see the varOffset in use
Code:
.text:0040175C CMYClassMethLnkTable: ; DATA XREF: .text:CMYClass_OptInfo_MethLnk↑o
.text:0040175C add dword ptr [esp+4], 3Ch ; '<'
.text:00401764 mov ecx, offset GetMem4
.text:00401769 jmp ecx
.text:0040176B ; ---------------------------------------------------------------------------
.text:0040176B add dword ptr [esp+4], 3Ch ; '<'
.text:00401773 mov ecx, offset PutMem4
.text:00401778 jmp ecx
.text:0040177A ; ---------------------------------------------------------------------------
.text:0040177A add dword ptr [esp+4], 40h ; '@'
.text:00401782 mov ecx, offset GetMemObj
.text:00401787 jmp ecx
.text:00401789 ; ---------------------------------------------------------------------------
.text:00401789 add dword ptr [esp+4], 40h ; '@'
.text:00401791 mov ecx, offset PutMemObj
.text:00401796 jmp ecx
.text:00401798 ; ---------------------------------------------------------------------------
.text:00401798 add dword ptr [esp+4], 40h ; '@'
.text:004017A0 mov ecx, offset SetMemObj
.text:004017A5 jmp ecx
and just for complete data visualization
Code:
.text:00402370 CMYClass_PrivateObj dd 0 ; nul1
.text:00402370 dd offset CMYClass_ObjInfo; lpParentLink
.text:00402370 dd 0FFFFFFFFh ; unk1
.text:00402370 dd 0 ; nul2
.text:00402370 dw 3 ; cntPublicVars
.text:00402370 dw 2 ; cntEvents
.text:00402370 dd 0 ; nul3
.text:00402370 dd offset CMYClass_FuncDesc; lpFuncTypeInfo
.text:00402370 dd 0 ; nul4
.text:00402370 dd offset CMYClass_Priv_PubVars; lpPublicVars
.text:00402370 dd offset CMYClass_Priv_EvtTypInf; lpEventsTypeInfo
.text:00402370 dd offset nullVal_3 ; lpNull
.text:00402370 dd 0 ; nul5
.text:00402370 dd 0 ; nul6
.text:00402370 dd 0 ; nul7
.text:00402370 dd 54h ; unk3
.text:00402370 dd 104h ; unk4
.text:00402104 CMYClass_Priv_PubVars dd offset CMYClass_PubVarTypDesc_0
.text:00402108 dd offset CMYClass_PubVarTypDesc_1
.text:004021A8 CMYClass_PubVarTypDesc_0 dd offset aA ; lpName
.text:004021A8 dd 0 ; nul1 ; "a"
.text:004021A8 dd 0 ; nul2
.text:004021A8 dw 0 ; index
.text:004021A8 db 3 ; unk1
.text:004021A8 db 40h ; unk2
.text:004021A8 dw 2 ; unk3
.text:004021A8 dw 1Ch ; vOff
.text:004021A8 dd 3Ch ; varOffset
.text:004021C0 dw 8
.text:004021C2 db 0
.text:004021C3 db 0
.text:00402168 CMYClass_PubVarTypDesc_1 dd offset aMypublicvar ; lpName
.text:00402168 dd 0 ; nul1 ; "myPublicVar"
.text:00402168 dd 0 ; nul2
.text:00402168 dw 1 ; index
.text:00402168 db 3 ; unk1
.text:00402168 db 40h ; unk2
.text:00402168 dw 2 ; unk3
.text:00402168 dw 24h ; vOff
.text:00402168 dd 40h ; varOffset
.text:00402180 dd 1Dh
.text:00402184 dd offset off_4023A4
all of those structures are automatically created and named from the IDC script generated by the IDC Structs node in the vbdec treeview
Last edited by dz32; Oct 25th, 2022 at 07:24 PM.
-
Oct 25th, 2022, 07:34 PM
#17
Re: [RESOLVED] VB6 COM/Code Object Method Name ---> vTable Entry Number
Also you should be able to extract the entire structure from memory with a copy memory call if you rather work with names fields
-
Oct 25th, 2022, 09:00 PM
#18
Re: [RESOLVED] VB6 COM/Code Object Method Name ---> vTable Entry Number
Ok, this is very nice. vOff (or lMethOffset as Trick calls it) is a bit strange.
The first two (low order) bits are some kind flags. The first one is a Public=1, Private/Friend=0 flag. I don't know what the second bit is. It's not Private vs Friend.
So, if we just go vOff = vOff \ 4 we then have a true zero-based offset (count) into the vTable.
If we further go vOff = vOff * 4 we then have a true "offset" into the vTable address for this method.
Or, since vTable offsets are always multiples of 4, a simple vOff = vOff And &FFFFFFFC then we've got the vTable offset address.
Last edited by Elroy; Oct 25th, 2022 at 09:03 PM.
Any software I post in these forums written by me is provided “AS IS” without warranty of any kind, expressed or implied, and permission is hereby granted, free of charge and without restriction, to any person obtaining a copy. Please understand that I’ve been programming since the mid-1970s and still have some of that code. My contemporary VB6 project is approaching 1,000 modules. In addition, I have a “VB6 random code folder” that is overflowing. I’ve been at this long enough to truly not know with absolute certainty from whence every single line of my code has come, with much of it coming from programmers under my employ who signed intellectual property transfers. I have not deliberately attempted to remove any licenses and/or attributions from any software. If someone finds that I have inadvertently done so, I sincerely apologize, and, upon notice and reasonable proof, will re-attach those licenses and/or attributions. To all, peace and happiness.
-
Oct 25th, 2022, 09:13 PM
#19
Re: [RESOLVED] VB6 COM/Code Object Method Name ---> vTable Entry Number
So, we can do the following and go straight from a method name to a vTable address offset (already multiplied by 4). Just need to add the vTable address to it and it takes us straight to the method's address in the object. And it searches Public, Private, & Friend methods. This is better than I'd hoped for.
Code:
Public Function VtableOffsetForVb6ComMethod(ByVal o As Object, ByVal sMethodName As String) As Long
' Searches Public, Friend, & Private methods.
' Does NOT search properties (i.e., Public variables).
' Returns an OFFSET address ready to be added to the vTable address.
' If a Get or Let/Set method is searched, the first one found will be returned (order in source code).
'
' If it can't be found, ZERO is returned.
'
If Not ObjectIsVb6ComCodeModule(o) Then Exit Function ' Make sure we're dealing with a VB6 COM-code object.
sMethodName = UCase$(sMethodName)
'
Dim pVTbl As Long: GetMem4 ByVal ObjPtr(o), pVTbl ' Pointer to vTable.
Dim pObjInfo As Long: GetMem4 ByVal pVTbl - 4&, pObjInfo ' Pointer to tObjectInfo structure.
Dim pPubDesc As Long: GetMem4 ByVal pObjInfo + &H18&, pPubDesc ' tObjectInfo.aObject which points to tObject structure.
Dim pPrivDesc As Long: GetMem4 ByVal pObjInfo + &HC&, pPrivDesc ' tObjectInfo.lpPrivateObject which points to tPrivateObj structure.
'
If pPrivDesc = 0& Then Exit Function ' Just a double-check.
'
Dim lIndex As Long
Dim pName As Long
'
' Search the procedures within the module.
Dim pMethDesc As Long
Dim lMethodsCnt As Long: GetMem2 ByVal pPubDesc + &H1C&, lMethodsCnt ' tObject.ProcCount value.
Dim pNames As Long: GetMem4 ByVal pPubDesc + &H20&, pNames ' tObject.aProcNamesArray which points to an array of name pointers.
Dim pMethodsPtr As Long: GetMem4 ByVal pPrivDesc + &H18&, pMethodsPtr ' tPrivateObj.lpFuncTypeInfo which points to an array of pointers.
'
' Loop through methods and see if we can find the one we want.
For lIndex = 0& To lMethodsCnt - 1&
GetMem4 ByVal pMethodsPtr + lIndex * 4&, pMethDesc ' From the array, getting a pointer to a method structure (tMethInfo).
If pMethDesc Then ' Not sure if this ever returns zero, maybe for "Private" methods?
GetMem4 ByVal pNames + lIndex * 4&, pName ' Dig pointer to method name from array of name pointers.
If sMethodName = UCase$(SysAllocStringByteLen(ByVal pName, lstrlenA(ByVal pName))) Then
Dim iMethOffset As Integer
GetMem2 ByVal pMethDesc + 2&, iMethOffset
VtableOffsetForVb6ComMethod = CLng(iMethOffset And &HFFFC)
Exit Function
End If
End If
Next
'
' Return zero if not found.
End Function
Any software I post in these forums written by me is provided “AS IS” without warranty of any kind, expressed or implied, and permission is hereby granted, free of charge and without restriction, to any person obtaining a copy. Please understand that I’ve been programming since the mid-1970s and still have some of that code. My contemporary VB6 project is approaching 1,000 modules. In addition, I have a “VB6 random code folder” that is overflowing. I’ve been at this long enough to truly not know with absolute certainty from whence every single line of my code has come, with much of it coming from programmers under my employ who signed intellectual property transfers. I have not deliberately attempted to remove any licenses and/or attributions from any software. If someone finds that I have inadvertently done so, I sincerely apologize, and, upon notice and reasonable proof, will re-attach those licenses and/or attributions. To all, peace and happiness.
-
Oct 25th, 2022, 10:18 PM
#20
Re: [RESOLVED] VB6 COM/Code Object Method Name ---> vTable Entry Number
Interesting. I haven’t explored these structures in the ide much just from compiled files.
For compiled files the array of the pubfuncdesc Pointers will have embedded nulls for any private or friend methods.
It makes sense in the ide there would be more info available and that some flag values may only have meaning within the ide since generated structures would best be reused.
Why they would superimpose a bit field on the low order bits they technically knew would never be used for the target data since it’s always mod 4 I dunno. That decision probably goes back to vb2 or 3 or something.
They do a similar thing with the “argsize” field. The first three bits are used to define if the method is a property get/let/set because valid values for the main use of this field are mod 4 as well. Flags can be 0 for subs, 1 for functions and oddly they set the bits 0xfc if the last parameter is a paramarray
We are dealing with code generated in old times.
Honestly one of the things I love about playing with this stuff is looking at the engineering of how it was done.
Last edited by dz32; Oct 29th, 2022 at 11:16 PM.
-
Oct 25th, 2022, 10:31 PM
#21
Re: [RESOLVED] VB6 COM/Code Object Method Name ---> vTable Entry Number
@dz32
I'm testing both running in IDE and running compiled (machine code). Everything is working both ways.
ADDED: Actually, I haven't tested that in the last hour or two. I'll check it now.
ADDED2: Ahh, crud, you're right. It only works on Public methods.
Any software I post in these forums written by me is provided “AS IS” without warranty of any kind, expressed or implied, and permission is hereby granted, free of charge and without restriction, to any person obtaining a copy. Please understand that I’ve been programming since the mid-1970s and still have some of that code. My contemporary VB6 project is approaching 1,000 modules. In addition, I have a “VB6 random code folder” that is overflowing. I’ve been at this long enough to truly not know with absolute certainty from whence every single line of my code has come, with much of it coming from programmers under my employ who signed intellectual property transfers. I have not deliberately attempted to remove any licenses and/or attributions from any software. If someone finds that I have inadvertently done so, I sincerely apologize, and, upon notice and reasonable proof, will re-attach those licenses and/or attributions. To all, peace and happiness.
-
Oct 26th, 2022, 04:30 AM
#22
Re: [RESOLVED] VB6 COM/Code Object Method Name ---> vTable Entry Number
Btw, this skips CLSIDFromString call
Code:
Public Function ObjectIsVb6ComCodeModule(o As IUnknown) As Boolean
Dim aGUID(0 To 1) As Currency ' {0B6C9465-D082-11CF-8B4F-00A0C90F2704}
aGUID(0) = 128347367577987.1845@
aGUID(1) = 29922525889064.5387@
ObjectIsVb6ComCodeModule = vbaCheckType(o, aGUID(0))
End Function
cheers,
</wqw>
-
Oct 26th, 2022, 09:12 AM
#23
Re: [RESOLVED] VB6 COM/Code Object Method Name ---> vTable Entry Number
Here is the article I mentioned describing some more details on the structures and bit field values. We can actually reconstruct the entire function prototype from the data embedded in these structures. It is part of how the vb idispatch plumbing operates.
https://decoded.avast.io/davidzimmer...6-executables/
This is how I spent my week vacation this year lol
(Along with learning to tig weld aluminum)
-
Oct 26th, 2022, 09:19 AM
#24
Re: [RESOLVED] VB6 COM/Code Object Method Name ---> vTable Entry Number
 Originally Posted by wqweto
Btw, this skips CLSIDFromString call
Code:
Public Function ObjectIsVb6ComCodeModule(o As IUnknown) As Boolean
Dim aGUID(0 To 1) As Currency ' {0B6C9465-D082-11CF-8B4F-00A0C90F2704}
aGUID(0) = 128347367577987.1845@
aGUID(1) = 29922525889064.5387@
ObjectIsVb6ComCodeModule = vbaCheckType(o, aGUID(0))
End Function
cheers,
</wqw>
Ahhh, I like it. I'll swap mine out. Thanks for figuring out those Currency constants. I'm hoping to make a "terse" version when I'm all done with this.
 Originally Posted by dz32
Here is the article I mentioned describing some more details on the structures and bit field values. We can actually reconstruct the entire function prototype from the data embedded in these structures. It is part of how the vb idispatch plumbing operates.
https://decoded.avast.io/davidzimmer...6-executables/
This is how I spent my week vacation this year lol
(Along with learning to tig weld aluminum)
Thanks dz32. I'll definitely read it. It looks like a good article.
Any software I post in these forums written by me is provided “AS IS” without warranty of any kind, expressed or implied, and permission is hereby granted, free of charge and without restriction, to any person obtaining a copy. Please understand that I’ve been programming since the mid-1970s and still have some of that code. My contemporary VB6 project is approaching 1,000 modules. In addition, I have a “VB6 random code folder” that is overflowing. I’ve been at this long enough to truly not know with absolute certainty from whence every single line of my code has come, with much of it coming from programmers under my employ who signed intellectual property transfers. I have not deliberately attempted to remove any licenses and/or attributions from any software. If someone finds that I have inadvertently done so, I sincerely apologize, and, upon notice and reasonable proof, will re-attach those licenses and/or attributions. To all, peace and happiness.
-
Oct 26th, 2022, 11:48 AM
#25
Re: [RESOLVED] VB6 COM/Code Object Method Name ---> vTable Entry Number
Sorry guys, I've been building since the summer so I can't be here most of the time, only in the evenings. All the undocumented things i obtained during reverse-engineering of the runtime/IDE. My mistake was i forgot to add pMembers += sizeof(PTR);
-
Oct 26th, 2022, 11:55 AM
#26
Re: [RESOLVED] VB6 COM/Code Object Method Name ---> vTable Entry Number
 Originally Posted by dz32
This is what trick had and -2 because they set bit 1 of that field as a flag for some reason.
As far as i know it's public/private bit.
-
Oct 26th, 2022, 11:57 AM
#27
Re: [RESOLVED] VB6 COM/Code Object Method Name ---> vTable Entry Number
We’re just a couple inches away from implementing reflection for all vb6 classes and forms now without needing tlbinf
Last edited by dz32; Oct 26th, 2022 at 12:01 PM.
-
Oct 26th, 2022, 11:59 AM
#28
Re: [RESOLVED] VB6 COM/Code Object Method Name ---> vTable Entry Number
 Originally Posted by dz32
They do a similar thing with the “argsize” field. The first three bits are used to define if the method is a property get/let/set because valid values for the main use of this field are mod 4 as well.
Code:
MethType = 2 ^ (MethType And &H3)
then
Code:
Select Case data(index).MethType
Case VbGet: sItem = "Public Property Get"
Case VbLet: sItem = "Public Property Let"
Case VbSet: sItem = "Public Property Set"
Case VbMethod: sItem = "Public Function"
Case 255: sItem = "Public Variable"
End Select
-
Oct 26th, 2022, 12:00 PM
#29
Re: [RESOLVED] VB6 COM/Code Object Method Name ---> vTable Entry Number
 Originally Posted by dz32
We’re just a couple inches away from implementing reflection for vb6 com objects now
If you (all) have questions you can ask i can check in IDA/Olly.
-
Oct 26th, 2022, 12:39 PM
#30
Re: [RESOLVED] VB6 COM/Code Object Method Name ---> vTable Entry Number
Cool thanks
-
Oct 26th, 2022, 01:20 PM
#31
Re: [RESOLVED] VB6 COM/Code Object Method Name ---> vTable Entry Number
Trick,
I think it's absolutely amazing, all the "tricks" you've provided on these forums.
You've pulled so many rabbits out of your hat that I think you've got a rabbit farm in there. 
You Take Care,
Elroy
Any software I post in these forums written by me is provided “AS IS” without warranty of any kind, expressed or implied, and permission is hereby granted, free of charge and without restriction, to any person obtaining a copy. Please understand that I’ve been programming since the mid-1970s and still have some of that code. My contemporary VB6 project is approaching 1,000 modules. In addition, I have a “VB6 random code folder” that is overflowing. I’ve been at this long enough to truly not know with absolute certainty from whence every single line of my code has come, with much of it coming from programmers under my employ who signed intellectual property transfers. I have not deliberately attempted to remove any licenses and/or attributions from any software. If someone finds that I have inadvertently done so, I sincerely apologize, and, upon notice and reasonable proof, will re-attach those licenses and/or attributions. To all, peace and happiness.
-
Oct 26th, 2022, 01:44 PM
#32
Re: [RESOLVED] VB6 COM/Code Object Method Name ---> vTable Entry Number
Couple of links explaining object info internals
https://www.hex-rays.com/products/id...eefiles/vb.idc
https://github.com/williballenthin/p...vb/__init__.py -- this one contains a lot of other links
Here is a memory dumping function I use to explore in Immediate Window
Code:
'--- mdDesignDump.bas
Option Explicit
Private Declare Sub CopyMemory Lib "kernel32" Alias "RtlMoveMemory" (Destination As Any, Source As Any, ByVal Length As Long)
Private Declare Function IsBadReadPtr Lib "kernel32" (ByVal lp As Long, ByVal ucb As Long) As Long
Public Function DesignDumpMemory(ByVal lPtr As Long, ByVal lSize As Long) As String
Dim lIdx As Long
Dim sHex As String
Dim sChar As String
Dim lValue As Long
Dim aResult() As String
ReDim aResult(0 To (lSize + 15) \ 16) As String
For lIdx = 0 To ((lSize + 15) \ 16) * 16
If lIdx < lSize Then
If IsBadReadPtr(lPtr, 1) = 0 Then
Call CopyMemory(lValue, ByVal lPtr, 1)
sHex = sHex & Right$("0" & Hex$(lValue), 2) & " "
If lValue >= 32 Then
sChar = sChar & Chr$(lValue)
Else
sChar = sChar & "."
End If
Else
sHex = sHex & "?? "
sChar = sChar & "."
End If
Else
sHex = sHex & " "
End If
If ((lIdx + 1) Mod 4) = 0 Then
sHex = sHex & " "
End If
If ((lIdx + 1) Mod 16) = 0 Then
aResult(lIdx \ 16) = Right$("000" & Hex$(lIdx - 15), 4) & " - " & sHex & sChar
sHex = vbNullString
sChar = vbNullString
End If
lPtr = (lPtr Xor &H80000000) + 1 Xor &H80000000
Next
DesignDumpMemory = Join(aResult, vbCrLf)
End Function
cheers,
</wqw>
Last edited by wqweto; Oct 26th, 2022 at 01:56 PM.
-
Oct 26th, 2022, 01:55 PM
#33
Re: [RESOLVED] VB6 COM/Code Object Method Name ---> vTable Entry Number
 Originally Posted by wqweto
Thanks for these. When you need this stuff, it's good to have it.
Any software I post in these forums written by me is provided “AS IS” without warranty of any kind, expressed or implied, and permission is hereby granted, free of charge and without restriction, to any person obtaining a copy. Please understand that I’ve been programming since the mid-1970s and still have some of that code. My contemporary VB6 project is approaching 1,000 modules. In addition, I have a “VB6 random code folder” that is overflowing. I’ve been at this long enough to truly not know with absolute certainty from whence every single line of my code has come, with much of it coming from programmers under my employ who signed intellectual property transfers. I have not deliberately attempted to remove any licenses and/or attributions from any software. If someone finds that I have inadvertently done so, I sincerely apologize, and, upon notice and reasonable proof, will re-attach those licenses and/or attributions. To all, peace and happiness.
-
Dec 3rd, 2022, 06:27 AM
#34
Re: [RESOLVED] VB6 COM/Code Object Method Name ---> vTable Entry Number
Starting to look into how implements works. It messes with the vtable and public variables table
http://sandsprite.com/blogs/index.ph...=517&year=2022
-
Dec 3rd, 2022, 08:06 AM
#35
Re: [RESOLVED] VB6 COM/Code Object Method Name ---> vTable Entry Number
 Originally Posted by dz32
Yeah, when I get a chunk of time, I need to look into this. I've just got several other things going on right now, but I'll get to it.
Any software I post in these forums written by me is provided “AS IS” without warranty of any kind, expressed or implied, and permission is hereby granted, free of charge and without restriction, to any person obtaining a copy. Please understand that I’ve been programming since the mid-1970s and still have some of that code. My contemporary VB6 project is approaching 1,000 modules. In addition, I have a “VB6 random code folder” that is overflowing. I’ve been at this long enough to truly not know with absolute certainty from whence every single line of my code has come, with much of it coming from programmers under my employ who signed intellectual property transfers. I have not deliberately attempted to remove any licenses and/or attributions from any software. If someone finds that I have inadvertently done so, I sincerely apologize, and, upon notice and reasonable proof, will re-attach those licenses and/or attributions. To all, peace and happiness.
Posting Permissions
- You may not post new threads
- You may not post replies
- You may not post attachments
- You may not edit your posts
-
Forum Rules
|
Click Here to Expand Forum to Full Width
|