# Visual Basic > Visual Basic 6 and Earlier >  how to list and call a vb6 std exe class,forms and  module methods

## smkperu

Hello Trick,

   Using *FireHacker's Name based object factory* we can identify all (classes,forms ,modules etc).

Can *you show me a vb6 working code example*  for the following:

how to list these (classes,forms,modules)methods and call them.

I know that we can use *vbanew* to create objects of forms,classes.
After creating the object using vbanew how to list and call their methods(class and form methods).

Similarly after listing Modules how to list their methods(module functionc) and call them.

For example suppose a vb6 std exe has a form1,class1 and a module1 each with one method Then how to list and call this methods thru their corresponding class object,form object and module.

Thanks

----------


## Arnoutdv

It really makes we wonder what kind of application needs these kind of hacks to function properly

----------


## Elroy

Be careful.  Not all of this works the same between compiled and running in the IDE.  Whenever you get something the way you like, be sure to compile it and make sure it still works.

Typically, all your "Private" and "Friend" procedures will disappear.  Also, I'm not sure if anything is available for BAS modules once compiled.

Some of what you're looking for can be found here.  Specifically, if you study that VtableOffsetForVb6ComMethod procedure, when supplied an object, you'll see that it's looping through all the methods of that object.  You could rearrange that to get a list of those methods.

----------


## Elroy

Also, on another thought, if you're just wanting something for the IDE, you could just write something (maybe an Add-In) to go through the source code.  Or, the extensibility model may already just have all of this.

----------


## smkperu

Hello Elroy,

  With *Trick's* CreatePrivateClass code shown below from modMultiThreading2.bas we can create a private class object using *vbaNew* from *vbheader info of std exe* and call their methods using *callbyname* or *dispcallfunc*.

Similarly I was asking a way to get the *address* of *module methods* after getting 
the *module name thru vbheader info* and call them using *dispcallfunc*.

*A simple example with only one form, one class and one module each with one  public method demo is enough for me*. 




```
' // Create private class
Private Function CreatePrivateClass( _
    ByVal pClassName As Long, _
    ByVal pIID As Long, _
    ByRef cObj As IUnknown) As Long
    Dim bIsInIDE        As Boolean
    Dim pProjInfo       As Long
    Dim pObjTable       As Long
    Dim pObjDesc        As Long
    Dim lTotalObjects   As Long
    Dim lIndex          As Long
    Dim lModuleType     As Long
    Dim sClassName      As String
    Dim pModname        As Long
    Dim pObjInfo        As Long
    Dim cTempObj        As IUnknown
    Dim iTypes(1)       As Integer
    Dim pArgs(1)        As Long
    Dim vArgs(1)        As Variant
    Dim vResult         As Variant
    
    Debug.Assert MakeTrue(bIsInIDE)
    
    If bIsInIDE Then
        
        sClassName = SysAllocStringByteLen(ByVal pClassName, lstrlen(pClassName))
        EbExecuteLine StrPtr("modMultithreading.QueueObject new " & sClassName), 0, 0, 0
        Set cTempObj = QueueObject(Nothing)
        
    Else
        
        ' // Go thru modules
        GetMem4 ByVal pVBHeader + &H30, pProjInfo
        GetMem4 ByVal pProjInfo + &H4, pObjTable
        GetMem2 ByVal pObjTable + &H2A, lTotalObjects
        GetMem4 ByVal pObjTable + &H30, pObjDesc
        
        For lIndex = 0 To lTotalObjects - 1
            
            GetMem4 ByVal pObjDesc + &H28, lModuleType
            GetMem4 ByVal pObjDesc + &H18, pModname
            
            ' // Only object modules
            If (lModuleType And 3) = 3 Then
                If lstrcmp(pClassName, pModname) = 0 Then
                    
                    GetMem4 ByVal pObjDesc, pObjInfo
                    Set cTempObj = vbaNew(ByVal pObjInfo)
                    
                    Exit For
                    
                End If
            End If
            
            pObjDesc = pObjDesc + &H30
            
        Next
        
    End If
    
    If cTempObj Is Nothing Then
        
        CreatePrivateClass = &H80040154
        Exit Function
        
    End If
    
    ' // Query interface
    iTypes(0) = vbLong:             iTypes(1) = vbLong
    vArgs(0) = pIID:                vArgs(1) = VarPtr(cObj)
    pArgs(0) = VarPtr(vArgs(0)):    pArgs(1) = VarPtr(vArgs(1))
    
    CreatePrivateClass = DispCallFunc(ByVal ObjPtr(cTempObj), 0, CC_STDCALL, vbLong, 2, iTypes(0), pArgs(0), vResult)
    
    If CreatePrivateClass >= 0 Then
        CreatePrivateClass = vResult
    End If
    
End Function
```

Thanks

----------


## wqweto

> With *Trick's* CreatePrivateClass code shown below from modMultiThreading2.bas we can create a private class object using *vbaNew* from *vbheader info of std exe* and call their methods using *callbyname* or *dispcallfunc*.


Why would you want to do this when you can always directly call *MyObj.MyMethod* even if MyObj is an instance of a private class.

Not to mention that you can *New MyClass* on private classes from within your project too, there is no need to "reflect" so much unless you are injecting a foreign process at which point I'll just shut up and advice everyone to withheld whatever advice they have here.

cheers,
</wqw>

----------


## smkperu

Hello wqw,

   Regarding classes I agree that we can use new.

   But  how is the  address of module methods found after getting
  the module name thru *vbheader* info  and call them using dispcallfunc.

Thanks

----------


## fafalone

I'm really hesitant to want topics censored because they can be misused, since even injecting foreign processes has legitimate uses and that knowledge should be available, but this guy has been consistently refusing to explain what he's trying to do for like a year now.

----------


## smkperu

> I'm really hesitant to want topics censored because they can be misused, since even injecting foreign processes has legitimate uses and that knowledge should be available, but this guy has been consistently refusing to explain what he's trying to do for like a year now.


Hello Fafalone,

  I am trying to understand how any vb6 std exe project executes its resources like forms, classes  etc from Trick's modMultiThreading code.

Thanks

----------


## Elroy

> But  how is the  address of module methods found after getting
>   the module name thru *vbheader* info  and call them using dispcallfunc.


Again, both finding the address to a Public method in an instantiated class (within your project) is outlined in post #3.  And also how you'd call it with dispcallfunc is also outlined.

Good luck with it.

----------


## smkperu

Hello Trick,

  I made a simple std exe application which identifies the Module1 present in
the project thru *projectinfo*(vbheader) when we click on the button on default form(Form1). using following code based on your modmultithreading module.



```
Private Sub Command1_Click()
sMethodName = UCase$("Module1")
    
    ''''''''''''''''''''''''''''''''
           Dim pProjInfo       As Long
    Dim pObjTable       As Long
    Dim pObjDesc        As Long
    Dim lTotalObjects   As Long
    Dim lIndex1          As Long
    Dim lModuleType     As Long
    Dim sClassName      As String
    Dim pModname        As Long
    Dim pObjInfo        As Long
    
    
      ' // Go thru modules
        GetMem4 ByVal pVBHeader + &H30, pProjInfo
        GetMem4 ByVal pProjInfo + &H4, pObjTable
        GetMem2 ByVal pObjTable + &H2A, lTotalObjects
        GetMem4 ByVal pObjTable + &H30, pObjDesc
         'MsgBox "for"
        For lIndex1 = 0 To lTotalObjects - 1
            
            GetMem4 ByVal pObjDesc + &H28, lModuleType
            GetMem4 ByVal pObjDesc + &H18, pModname
            
         
                If sMethodName = UCase$(SysAllocStringByteLen(ByVal pModname, lstrlen(ByVal pModname))) Then
                    
                  MsgBox "Found " & UCase$(SysAllocStringByteLen(ByVal pModname, lstrlen(ByVal pModname))) ' success 
                  GetMem4 ByVal pObjDesc, pObjInfo
                    
                    Exit For
                    
                End If
           
            
            pObjDesc = pObjDesc + &H30
            
        Next

        'How to identify Module1 method modfunc1 and run it
   
 
End Sub
```


Now how can I identify method *modfunc1* from the Module1 module and run it.

Project attached 

Thanks

----------


## smkperu

Hello Trick & Elroy,

Once address is available I understood how to call module function/sub using
https://www.vbforums.com/showthread....ure-By-Address
using DispCallfunc.Thanks to Elroy.

I know that we can use *addressof* operator for calling standard module functions
in a std exe project.

But if we don't have any forms or classes and only standard module in the project how will sub main call any user defined module method from the module *internally* thru projectinfo(vbheader).

Thanks

----------


## Elroy

Smkperu, I'm certainly open to being proven wrong, but I don't believe anything about a list of procedure names is saved for BAS modules once the program is compiled.  And, anything that's not available once compiled, I wouldn't want to use in the IDE.

----------


## smkperu

> Smkperu, I'm certainly open to being proven wrong, but I don't believe anything about a list of procedure names is saved for BAS modules once the program is compiled.  And, anything that's not available once compiled, I wouldn't want to use in the IDE.


Hello Elroy,

      It is not that I want to prove anybody wrong.
      Already you have shown how to call module functions thru *private objects
      like forms and classes* and how to use *DispCallFunc* with standard module 
      functions.
      When it is possible using objects thru projectinfo or vbheader even in compiled 
      code  then *why not for  standard module functions directly* without using them 
      thru instantiated objects.

Thanks

----------


## Elroy

> Hello Elroy,
> 
>       It is not that I want to prove anybody wrong.
>       Already you have shown how to call module functions thru *private objects
>       like forms and classes* and how to use *DispCallFunc* with standard module 
>       functions.
>       When it is possible using objects thru projectinfo or vbheader even in compiled 
>       code  then *why not for  standard module functions directly* without using them 
>       thru instantiated objects.
> ...


Ahhh, ok, I think I can answer that question.

All "objects" (forms, classes, user controls, data reports) have what's called a VTable which jumps into each of the procedures it contains.  Furthermore, for late-bound purposes, these objects maintain a "lookup list" of all the *Public* procedures within the objects.  That's why this works with objects.  However, BAS modules are not objects (at least not in the strictest sense), and therefore don't have VTables nor lookup lists.  When compiled, any Intellisense-type lookup list that existed is thrown out because it's just not needed.

----------


## smkperu

> Ahhh, ok, I think I can answer that question.
> 
> All "objects" (forms, classes, user controls, data reports) have what's called a VTable which jumps into each of the procedures it contains.  Furthermore, for late-bound purposes, these objects maintain a "lookup list" of all the *Public* procedures within the objects.  That's why this works with objects.  However, BAS modules are not objects (at least not in the strictest sense), and therefore don't have VTables nor lookup lists.  When compiled, any Intellisense-type lookup list that existed is thrown out because it's just not needed.


Hello Elroy,


  You are accessing thru instantiated objects using *vTable*.But I was asking *Trick* thru
*vbheader* for accessing *already existing global things* like *standard Modules* and *their method
addresses*.For example you can access even *existing  form object*(instantiated object) thru *vbheader*.

Thanks

----------


## smkperu

Hello Trick,

  We can identify *instantiated form objects* from *vbheader* thru *Forms* collection object.
How can we identify instantiated *class* objects and *modules* thru vbheader.

Thanks

----------

