Page 1 of 2 12 LastLast
Results 1 to 40 of 67

Thread: internals of activex exe buit in CreateObject multithreading vs CreateThread api

  1. #1

    Thread Starter
    Hyperactive Member
    Join Date
    Apr 2015
    Posts
    356

    internals of activex exe buit in CreateObject multithreading vs CreateThread api

    Dear Trick,

    This is to understand how vb6 implements built in multithreading for activex exe using CreateObject.

    I understand that we can do multithreading in activex exe in three ways:

    1. by using a std exe and loading a activex exe in activex component mode with Thread per object setting.
    2. by using activex exe directly in standalone mode with Thread per object setting.
    3. by using activex exe directly in standalone mode with Thread Pool.

    We can omit option 1. since it involves two processes (std exe and activex exe) running having more switching overhead
    between the two processes.

    With option 2. we will be using the vb6 built in multithreading capability.

    With option 3. when we set thread pool to n, n threads are created.

    With option2 we can use either built in multithreading capability (CreateObject) or CreateThread api with vbheader as in standard exe.

    With option3 when we set Thread Pool to 1 we can again create multiple threads using CreateThread api with vbheader as in standard exe independent of the thread pool option set to 1.

    Can you clarify me through example which is better to use of CreateObject built in option or CreateThread Api.
    What is the difference between the two approaches ie built in CreateObject and CreateThread api with vbheader.



    regards,
    JSVenu

  2. #2
    PowerPoster
    Join Date
    Feb 2015
    Posts
    2,687

    Re: internals of activex exe buit in CreateObject multithreading vs CreateThread api

    When you have Thread Pool it means you have the fixed set of the thread you can use. For example if you have 1 it means only 1 thread you can use. All the objects you create will have the shared variables and will live in that single thread.

    What is the difference between the two approaches ie built in CreateObject and CreateThread api with vbheader.
    You shouldn't use this approach (vbheader) to AxEXE. You can't run an ActiveX EXE if you have no permissions (for first time).

  3. #3

    Thread Starter
    Hyperactive Member
    Join Date
    Apr 2015
    Posts
    356

    Re: internals of activex exe buit in CreateObject multithreading vs CreateThread api

    Quote Originally Posted by The trick View Post
    When you have Thread Pool it means you have the fixed set of the thread you can use. For example if you have 1 it means only 1 thread you can use. All the objects you create will have the shared variables and will live in that single thread.


    You shouldn't use this approach (vbheader) to AxEXE. You can't run an ActiveX EXE if you have no permissions (for first time).
    Dear Trick,

    First thankyou for the reply.


    Code:
    Public Function InitVbProjContext() As IUnknown
        Dim pVBHeader       As Long
        Dim pCOMData        As Long
        Dim lOfstRegInfo    As Long
        Dim pRegInfo        As Long
        Dim pfn             As Long
        Dim hLib            As Long
        Dim iTypes(2)       As Integer
        Dim vParams(2)      As Variant
        Dim lList(2)        As Long
        Dim bIID(1)         As Currency
        Dim cFactory        As IUnknown
        Dim cObject         As IUnknown
        Dim hr              As Long
        Dim vRet            As Variant
        
        hLib = GetModuleHandle(StrPtr("actxdllwithapt_threaded.dll"))
        pfn = GetProcAddress(hLib, "DllGetClassObject")
        If pfn = 0 Then Exit Function
        
        ' // Get VBHeader
        GetMem4 ByVal pfn + 2, pVBHeader
        ' // Get COM data
        GetMem4 ByVal pVBHeader + &H54, pCOMData
        ' // Get Reg info
        GetMem4 ByVal pCOMData, lOfstRegInfo
        
        pRegInfo = pCOMData + lOfstRegInfo
    
        ' // IClassFactory
        bIID(0) = 0.0001@
        bIID(1) = 504403158265495.5712@
    
        hr = DllGetClassObject(ByVal pRegInfo + &H14, bIID(0), cFactory)
        
        If hr >= 0 And Not cFactory Is Nothing Then
            
            ' // Call IClassFactory::CreateInstance
    
            iTypes(0) = vbLong
            iTypes(1) = vbLong
            iTypes(2) = vbLong
    
            bIID(0) = 0
            
            vParams(0) = 0&
            vParams(1) = VarPtr(bIID(0))
            vParams(2) = VarPtr(cObject)
            
            lList(0) = VarPtr(vParams(0))
            lList(1) = VarPtr(vParams(1))
            lList(2) = VarPtr(vParams(2))
    
            hr = DispCallFunc(ByVal ObjPtr(cFactory), &HC, CC_STDCALL, vbLong, 3, iTypes(0), lList(0), vRet)
            
            If hr >= 0 And vRet >= 0 Then
    
                Set InitVbProjContext1 = cObject
    
            End If
            
        End If
    
    End Function

    Using the above code you have already shown how the activex dll implements the multiuse class internally
    through the exported DllGetClassObject starting from which we get classfactory object.

    But here activex exe does not export DllGetClassObject so there will be some other way to get classfactory object which will help in initializing the runtime of threadproc.Please clarify with a similar working example code so that I can understand internally how the activex exe creates a thread and initialises its runtime without having to use the multiuse class through CreateObject as you have already shown above using DllGetClassObject and DispCallFunc for activex dll.



    regards,
    JSVenu

  4. #4

    Thread Starter
    Hyperactive Member
    Join Date
    Apr 2015
    Posts
    356

    Re: internals of activex exe buit in CreateObject multithreading vs CreateThread api

    Quote Originally Posted by jsvenu View Post
    Dear Trick,

    First thankyou for the reply.


    Code:
    Public Function InitVbProjContext() As IUnknown
        Dim pVBHeader       As Long
        Dim pCOMData        As Long
        Dim lOfstRegInfo    As Long
        Dim pRegInfo        As Long
        Dim pfn             As Long
        Dim hLib            As Long
        Dim iTypes(2)       As Integer
        Dim vParams(2)      As Variant
        Dim lList(2)        As Long
        Dim bIID(1)         As Currency
        Dim cFactory        As IUnknown
        Dim cObject         As IUnknown
        Dim hr              As Long
        Dim vRet            As Variant
        
        hLib = GetModuleHandle(StrPtr("actxdllwithapt_threaded.dll"))
        pfn = GetProcAddress(hLib, "DllGetClassObject")
        If pfn = 0 Then Exit Function
        
        ' // Get VBHeader
        GetMem4 ByVal pfn + 2, pVBHeader
        ' // Get COM data
        GetMem4 ByVal pVBHeader + &H54, pCOMData
        ' // Get Reg info
        GetMem4 ByVal pCOMData, lOfstRegInfo
        
        pRegInfo = pCOMData + lOfstRegInfo
    
        ' // IClassFactory
        bIID(0) = 0.0001@
        bIID(1) = 504403158265495.5712@
    
        hr = DllGetClassObject(ByVal pRegInfo + &H14, bIID(0), cFactory)
        
        If hr >= 0 And Not cFactory Is Nothing Then
            
            ' // Call IClassFactory::CreateInstance
    
            iTypes(0) = vbLong
            iTypes(1) = vbLong
            iTypes(2) = vbLong
    
            bIID(0) = 0
            
            vParams(0) = 0&
            vParams(1) = VarPtr(bIID(0))
            vParams(2) = VarPtr(cObject)
            
            lList(0) = VarPtr(vParams(0))
            lList(1) = VarPtr(vParams(1))
            lList(2) = VarPtr(vParams(2))
    
            hr = DispCallFunc(ByVal ObjPtr(cFactory), &HC, CC_STDCALL, vbLong, 3, iTypes(0), lList(0), vRet)
            
            If hr >= 0 And vRet >= 0 Then
    
                Set InitVbProjContext1 = cObject
    
            End If
            
        End If
    
    End Function

    Using the above code you have already shown how the activex dll implements the multiuse class internally
    through the exported DllGetClassObject starting from which we get classfactory object.

    But here activex exe does not export DllGetClassObject so there will be some other way to get classfactory object which will help in initializing the runtime of threadproc.Please clarify with a similar working example code so that I can understand internally how the activex exe creates a thread and initialises its runtime without having to use the multiuse class through CreateObject as you have already shown above using DllGetClassObject and DispCallFunc for activex dll.



    regards,
    JSVenu
    Dear trick,

    After digging deeper I found that activex exe uses CoRegisterClassObject similar to DllGetClassObject used for
    activex dll.Can you provide a sample for the same.

    regards,
    JSVenu

  5. #5

    Thread Starter
    Hyperactive Member
    Join Date
    Apr 2015
    Posts
    356

    Re: internals of activex exe buit in CreateObject multithreading vs CreateThread api

    Dear Trick,

    In a standard exe when we start a new thread we have vbheader thru which we can control the way the new thread behaves like bypass startup form or submain.

    But is there any way to achieve the same in activex exe in standalone mode like vbheader since thread is by default created out of the box when we use CreateObject.Here what is the mechanism which starts the thread and inits its runtime.We know that activex exe has only two options submain and none.The object in the new thread is created using CoRegisterClassObject , .. , CoRevokeClassObject.Please clarify.


    regards,
    JSVenu

  6. #6

    Thread Starter
    Hyperactive Member
    Join Date
    Apr 2015
    Posts
    356

    Re: internals of activex exe buit in CreateObject multithreading vs CreateThread api

    Dear Trick,

    I can sincerely tell you that I could get the two differences when we use activex exe instead of activex dll through the following good article
    https://www.codeproject.com/articles...d-apartment-pa as follows:

    Main differences between a DLL server and an EXE server

    Difference 1: The Way Objects Are Created

    When COM wishes to create a COM object which is implemented inside a DLL, it loads the DLL, connects with its exported DllGetClassObject() function, calls it, and obtains a pointer to the IClassFactory interface of the class factory object of the COM object. It is from this IClassFactory interface pointer that the COM object is created.

    The story with EXE Servers has the same eventuality: obtaining the IClassFactory interface pointer of the class factory object of the COM object to be created and then creating the COM object through it. What happens before that is the difference between a DLL server and an EXE Server.

    A DLL server exports the DllGetClassObject() function for COM to extract the class factory but an EXE server cannot export any function. An EXE server instead has to register its class factory in the COM sub-system when it starts up, and then revoke the class factory when it shuts down. This registration is done via the API CoRegisterClassObject().

    Difference 2: The Way The Apartment Model Of Objects Are Indicated

    Objects implemented in DLLs indicate their Apartment Models by appropriately setting the "ThreadingModel" registry string value which is located in the object's "InProcServer32" registry entry.

    Objects implemented in an EXE server do not set this registry value. Instead, the Apartment Model of the thread which registers the object's class factory determines the object's Apartment Model.

    But since the code is in c/c++ no where there is mention of how activex exe in vb6 creates and inits thread runtime out of the box when run in standalone mode with Thread per object.Please clarify.

    regards,
    JSVenu

  7. #7

  8. #8

    Thread Starter
    Hyperactive Member
    Join Date
    Apr 2015
    Posts
    356

    Re: internals of activex exe buit in CreateObject multithreading vs CreateThread api

    Quote Originally Posted by The trick View Post
    I don't understand your questions.
    Dear Trick,

    Ok sorry I might not have explained you in better way what I my doubt is.

    1. We have standard exe which can create thread using createthread api and initialize it using vbdllgetclassobject.

    2. We have standard dll which can create thread using createthread api and initialize it using vbdllgetclassobject.

    3. We have activex dll which can create thread using createthread api and initialize it using CreateObject with multiuse class or dllgetclassobject and dispcallfunc or directly using vbdllgetclassobject at low level since dllgetclassobject calls anyway vbdllgetclassobject internally.

    4. You have already shown internals of all the above three projects (std exe,std dll,actx dll) working practically which I understood.

    5. Similarly I was asking how a activex exe internally creates a thread and initializes its runtime out of the box using CreateObject through its multiuse class when run in standalone mode.Without using multiuse class just as activex dll
    can the new thread runtime be initialized in activex exe. Please clarify.


    regards,
    JSVenu

  9. #9

    Thread Starter
    Hyperactive Member
    Join Date
    Apr 2015
    Posts
    356

    Re: internals of activex exe buit in CreateObject multithreading vs CreateThread api

    Dear Trick,

    To be even more clear I am sending a simple activex exe example which displays new form object in new thread each time when we click on Display form in new thread button on the displayed main form of activex exe.

    Here the main disadvantage is that the displayed form is in thread is only modeless using CreateObject since it is async in nature and not true free threading since we cannot display modal form in new thread.

    Here can we replace the CreateObject with any alternate method so that free threading is possible without using the cThread multiuse class in CreateObject and achieve the same in a sync way in this activex exe.


    regards,
    JSVenu
    Attached Files Attached Files
    Last edited by jsvenu; Apr 5th, 2020 at 07:33 AM.

  10. #10

    Thread Starter
    Hyperactive Member
    Join Date
    Apr 2015
    Posts
    356

    Re: internals of activex exe buit in CreateObject multithreading vs CreateThread api

    Dear Trick,

    In the above AxExeServer.zip I mean if we change the code as follows it will not work.

    Code:
    Public Sub RunOnThreadClass()
        Dim x As New Form2
        x.Show vbModal
    End Sub
    It works only when we remove vbModal since it is async in nature.How to make it work even with vbModal in activex exe running in standalone mode.Is there any other method with which we can replace CreateObject with multiuse class so that this works.
    I donot bother compiling in with admin privileges first time which I do by default for any activex exe.
    regards,
    JSVenu

  11. #11
    PowerPoster
    Join Date
    Jun 2013
    Posts
    7,253

    Re: internals of activex exe buit in CreateObject multithreading vs CreateThread api

    Quote Originally Posted by jsvenu View Post
    In the above AxExeServer.zip I mean if we change the code as follows it will not work.

    Code:
    Public Sub RunOnThreadClass()
        Dim x As New Form2
        x.Show vbModal
    End Sub
    It was mentioned several times already, that method-calls on "STA-hosted WorkerObjects" are synchronous.
    It was also mentioned, that an API-free and easy way for "asnyc decoupling" is,
    to just use a simple VB.Timer-Control (e.g. placed as Timer1, Enabled=False, Interval=10 on your ThreadForm).

    Updated Worker-Class-Code for async-dcoupling via Timer:
    Code:
     
    Public Sub RunOnThreadClass()
        Dim x As New Form2
            x.Timer1.Enabled = True
    End Sub
    And the updated ThreadForm-Code, now entering a "longer, blocking routine", from inside the Timer-Event:
    Code:
    Private Sub Form_Load()
      Me.Caption = "Form in thread - ThreadID: " & App.ThreadID
    End Sub
    
    Private Sub Timer1_Timer()
        Timer1.Enabled = False 'disable the Timer again
        Show vbModal '<- now we can enter the longer blocking method from the inside of our ThreadWorker-Object
    End Sub
    Hopefully this was your last question on that topic, because it really gets annoying in the meantime -
    (since we explain basically the same thing over and over again).

    You have now explored "a dozen different ways, to show VB6-Forms on their own threads" -
    this should be reason enough for you, to not explore another "exotic Form-Showing-method now"...

    Please stop this - and perhaps think about, how you can come up with a more "real world usecase" for threading.
    These synthetic examples will teach you nothing really...

    Olaf

  12. #12

    Thread Starter
    Hyperactive Member
    Join Date
    Apr 2015
    Posts
    356

    Re: internals of activex exe buit in CreateObject multithreading vs CreateThread api

    Dear Olaf,

    Thankyou.

    regards,
    JSVenu

  13. #13

  14. #14

    Thread Starter
    Hyperactive Member
    Join Date
    Apr 2015
    Posts
    356

    Re: internals of activex exe buit in CreateObject multithreading vs CreateThread api

    Dear Trick,

    Thankyou very much for showing the internals thru ollydbg.

    regards,
    JSVenu

  15. #15
    PowerPoster
    Join Date
    Jan 2020
    Posts
    3,749

    Re: internals of activex exe buit in CreateObject multithreading vs CreateThread api

    maybe activex use "rot",
    Code:
     lp = RegisterActiveObject(up, mGuid, ACTIVEOBJECT_WEAK, OLEInstance)
    activex.exe “ /regserver”,it's only write tlb info to reg key/value?
    ,and write the exe file path。
    rot need run activex exe first。
    so,it's not activex.dll,so it can be call by x64
    process

  16. #16
    PowerPoster
    Join Date
    Jan 2020
    Posts
    3,749

    Re: internals of activex exe buit in CreateObject multithreading vs CreateThread api

    activex exe ie active object? is not activex dll?

  17. #17

    Thread Starter
    Hyperactive Member
    Join Date
    Apr 2015
    Posts
    356

    Re: internals of activex exe buit in CreateObject multithreading vs CreateThread api

    Quote Originally Posted by The trick View Post
    The runtime creates and manages threads when you create an ActiveX-Object-instance. The created instance then is marshaled to caller thread. Just the call stacks when you create an AxObj instance:
    Dear Trick,

    As per the above callstack the CreateObject of activex exe calls CreateThread which
    calls _beginThreadEx and then calls CThreadPool::InitExeThrd which
    internally calls CThreadPool::_InitThread
    Here can you show the code for how the CThreadPool::_InitThread internally
    initialises the runtime of default created Thread's ThreadProc
    in this activex exe
    .
    ( For a activex dll you already explained me how to initialize runtime of Threadproc by using CoInitalize
    followed by CreateObject and this CreateObject can be internally replaced using DllGetClassObject and
    DispCallFunc for creating Class factory object which I understood ).

    regards,
    JSVenu
    Last edited by jsvenu; Apr 7th, 2020 at 08:03 AM.

  18. #18

    Thread Starter
    Hyperactive Member
    Join Date
    Apr 2015
    Posts
    356

    Re: internals of activex exe buit in CreateObject multithreading vs CreateThread api

    Dear Trick,

    In activex exe when it runs in standalone mode:

    When we start a Thread in activex exe by running it in a standalone mode with Thread per Object setting using
    CreateObject and to this CreateObject if we input parameter as multiuse class it works perfect.
    But when we pass a singleuse class to CreateObject it behaves in a different way.First time it behaves as if in the same
    thread and from next time it behaves correctly.This can be observed by setting cThread object to multiuse and Single
    use instancing in the sample with link below
    http://www.vbforums.com/attachment.p...3&d=1586089812 .
    Why.

    In activex exe when it runs in activex component mode:

    When we start a thread of activex exe in activex component mode with thread per object setting and start its thread
    from a standard exe by including activex in std exe thru project setting and start the thread using CreateObject even
    with singleuse class
    it works perfect as in the sample attached which contains both std exe and actx exe.Why.

    This is the reason I asked how does activex exe inits runtime for threadproc when new thread is started using CreateObject with input class object parameter with singleuse or multiuse instancing.Please clarify.

    regards,
    JSVenu
    Attached Files Attached Files

  19. #19

    Thread Starter
    Hyperactive Member
    Join Date
    Apr 2015
    Posts
    356

    Re: internals of activex exe buit in CreateObject multithreading vs CreateThread api

    Dear Trick,


    I know that activex exe with threading model as Thread pool = 1 running in standalone mode is eqivalent to standard exe only with one difference that first time the activex exe should run with admin privilege.I already know how to initialize runtime for the threadproc created using CreateThread API using vbheader.

    But if I want to create a normal CreateThread api based thread in activex exe running in standalone mode with Thread per object or Thread Pool > 1 threading model what is the code to initialize runtime for the created ThreadProc.Please clarify for which I shall be thankful to you.

    regards,
    JSVenu

  20. #20
    PowerPoster
    Join Date
    Jun 2013
    Posts
    7,253

    Re: internals of activex exe buit in CreateObject multithreading vs CreateThread api

    Quote Originally Posted by jsvenu View Post
    But if I want to create a normal CreateThread api based thread in activex exe running in standalone mode...
    You *don't* want to do that, because as soon as you do, you'll start "walking on thin ice"
    (writing VB6-Code directly into freethreaded-callbacks, has to happen under very narrow and restricting rules).

    That was explained to you several times already.
    What the trick does with the vbHeader-hack, is lowering a few of the above mentioned restrictions (not all),
    and not only Newbies, but also "normally experienced Users" are risking crashes when going that way...

    The only safe way to do threading in VB6 (writing stuff in your UserCode without any restrictions):
    - is to stick with AxExe-Threading (where the VBRuntime establishes Objects on STAs for you)
    - or to use a *compiled* binary (Flat-Dll or AxDll) which establishes these WorkerObjects on STAs

    I don't know, how many times I've had to repeat this over the last months...

    Please learn how to work with these "STA-WorkerObjects" - they are nice and safe to use
    (although there are some pecularities, one has to gather experience with).

    And yes, such STA-based solutions will look different from implementations in other languages,
    which use freethreading (freethreaded callbacks) - but you can solve the same problems with them
    (with about the same amount of code-lines, or less)

    Olaf

  21. #21

    Thread Starter
    Hyperactive Member
    Join Date
    Apr 2015
    Posts
    356

    Re: internals of activex exe buit in CreateObject multithreading vs CreateThread api

    Dear Olaf,

    Your ThreadedSTAs.dll is similar to Srideep's solution (https://www.planet-source-code.com/v...26900&lngWId=1) which I already mentioned in the link
    http://www.vbforums.com/showthread.p...rom-The-Trick) #12 on May 26th 2015

    You have already given solution of ThreadedSTAs.dll activex dll for doing multithreading in std exe using it.
    You told the ThreadedSTAs.dll when used with apartment threaded is not useful.But we can work with it if we change the code in it so that it can work both as single threaded and apartment threaded without crash in a stable way.
    Same is the case with WorkerLib.dll of ThreadFormInDll.It also can be made to work equally better in both as single threaded and apartment threaded without crash in a stable way.

    You told we cannot use exe forms in new thread for which I already showed how to do them with example even in single and apartment thread.

    You showed how to use async decouple which I am satisfied (using postmessage,postthreadmessage or timer control) or using even settimer api call without using timer control.

    Even the activex exe example which you gave for the first time for adding runtime usercontrol at runtime I already solved it just by setting the exe's vbheader to apartment model just before adding it to new form thread and then after completing this runtime adding we reset the model back to default model using the vbheader which worked perfect for me. It was for this there was a lot of friction between you and Trick but I could make it work perfect.

    I donot think there is wrong in using normal CreateThread api in activex exe just as in activex dll.

    I donot have any intention of hijacking or stopping anybody's thread. I want to tell that I really appreciate for the help and donot restrict anybody completely.I hope you please understand me.

    regards,
    JSVenu

  22. #22

  23. #23
    PowerPoster
    Join Date
    Jun 2013
    Posts
    7,253

    Re: internals of activex exe buit in CreateObject multithreading vs CreateThread api

    Quote Originally Posted by jsvenu View Post
    I already showed how to do them with example even in single and apartment thread.
    And you were already told, that switching an (by default apartment-threaded) AxDll-Project .
    into single-threaded mode is absolutely pointless, because it's an older modus, which is only
    there to ensure some backwards-compatibility to older VB-versions.

    If you think, Ax-Dlls (compiled in single-threaded mode) are useful for something,
    (which cannot be achieved with an Ax-Dll in its default-apartment-threaded-mode),
    then you should show an example (which you can't).

    So you're wasting your own time (as well as the time of other forum-members) here,
    by trying to "make this old stuff work" (with weird hacks), when there's no need to,
    because the "more recent default-stuff" already works without any hacks, when it comes to threading.

    I've still not seen any useful real-world threading-example from you in all those threads you triggered.
    All you do (since 2015), is showing "empty Forms" - but that's not what threading is used for.

    Olaf

  24. #24

    Thread Starter
    Hyperactive Member
    Join Date
    Apr 2015
    Posts
    356

    Re: internals of activex exe buit in CreateObject multithreading vs CreateThread api

    Quote Originally Posted by The trick View Post
    Why do you need such initialization? AXExe already have such initialization out-of-box.
    Dear Trick,

    But AXExe has initialization of Threadproc using CThreadPool::_InitThread out-of-box thru CreateObject and wanted to init runtime for new threadproc using CreateThread API instead just as I do in

    1. Std exe using

    Code:
     Public Function  ThreadProc(...)
                 'init runtime
                      Set cExpSrv = CreateIExprSrvObj(0, 4, 0)
                      CoInitialize ByVal 0&
                      vbdllgetclassobject(...)
                  'End of init runtime for this threadproc
                  
                  ' do anything in this thread              
    
    END Function
    2. Actx dll using

    Code:
    Public Function  ThreadProc(...)
                 'init runtime
                       Set cExpSrv = CreateIExprSrvObj(0, 4, 0)
                      CoInitialize ByVal 0&
    
                       ' // IClassFactory
                        ...
    
                        hr = DllGetClassObject(...)
        
                        ...
            
                         ' // Call IClassFactory::CreateInstance
    
                          ...
                          hr = DispCallFunc(...)
               'End of init runtime for this threadproc
                        
                         ' do anything in this thread
    
    END Function



    regards,
    JSVenu

  25. #25
    PowerPoster
    Join Date
    Jun 2013
    Posts
    7,253

    Re: internals of activex exe buit in CreateObject multithreading vs CreateThread api

    Quote Originally Posted by jsvenu View Post
    ...wanted to init runtime for new threadproc using CreateThread API instead just as I do in

    1. Std exe using

    Code:
     Public Function  ThreadProc(...)
                 'init runtime
                      Set cExpSrv = CreateIExprSrvObj(0, 4, 0)
                      CoInitialize ByVal 0&
                      vbdllgetclassobject(...)
                  'End of init runtime for this threadproc
                  
                  ' do anything in this thread              
    
    END Function
    You're not listening...

    As I wrote already, you definitley cannot "do anything" in such freethreaded callbacks.

    Instead you are restricted (in your UserCode) to "certain operations only"
    (because VB6 was not made with "full freethreading support").

    Only the STA-based threading-model is fully supported by VB6 - which then allows you,
    to really "do anything" VB6 and its Runtime has to offer, without any restrictions...
    (in the UserCode you type into both - your Main- and ThreadWorkerDll-Projects).

    Why this simple stability-related fact is so hard to understand, is beyond me...

    Olaf

  26. #26
    PowerPoster
    Join Date
    Feb 2015
    Posts
    2,687

    Re: internals of activex exe buit in CreateObject multithreading vs CreateThread api

    But AXExe has initialization of Threadproc using CThreadPool::_InitThread out-of-box thru CreateObject and wanted to init runtime for new threadproc using CreateThread API instead just as I do in
    Those function aren't exported you can't call them directly like VBDllGetClassObject. If you need you could use a restricted code in an AxEXE-thread without any initialization like i did in the CallbackDll. Why don't you want to use that approach?

  27. #27

    Thread Starter
    Hyperactive Member
    Join Date
    Apr 2015
    Posts
    356

    Re: internals of activex exe buit in CreateObject multithreading vs CreateThread api

    Quote Originally Posted by The trick View Post
    Those function aren't exported you can't call them directly like VBDllGetClassObject. If you need you could use a restricted code in an AxEXE-thread without any initialization like i did in the CallbackDll. Why don't you want to use that approach?
    Dear Trick,

    We have to use CoRegisterClassObject instead of DllGetClassObject in the following code which I already showed for activex dll as follows since I already told that DllGetClassObject is not exported in #3 above.(Here I think we have to give some default class of activex exe running in standalone mode as input to CoRegisterClassObject).

    Code:
    Public Function  ThreadProc(...)
                 'init runtime
                       Set cExpSrv = CreateIExprSrvObj(0, 4, 0)
                      CoInitialize ByVal 0&
    
                       ' // IClassFactory
                        ...
    
                        hr = DllGetClassObject(...)  'has to be replaced by CoRegisterClassObject 
        
                        ...
            
                         ' // Call IClassFactory::CreateInstance
    
                          ...
                          hr = DispCallFunc(...)
               'End of init runtime for this threadproc
                        
                         ' do anything in this thread
    
    END Function
    If we could use CoRegisterGetClassObject with some default class of activex exe in place of DllGetClassObjectwe should be able to initruntime.
    Please clarify how to use CoRegisterGetClassObject so that ThreadProc runtime can be initialized when we use CreateThread API.

    regards,
    JSVenu

  28. #28

  29. #29

    Thread Starter
    Hyperactive Member
    Join Date
    Apr 2015
    Posts
    356

    Re: internals of activex exe buit in CreateObject multithreading vs CreateThread api

    Quote Originally Posted by The trick View Post
    CoRegisterGetClassObject registers the class factory (already created by runtime). CreateObject calls CoCreateInstance which calls IClassFactory::CreateInstance. This function creates a thread (if need) and creates an instance in that thread then it marshals the reference to the caller thread.
    CreateThread is called by runtime.
    Dear Trick,

    This is what I wanted to do by explicitly using CreateThread so that I can init my ThreadProc instead of using CreateObject directly in activex exe running in standalone mode.

    regards,
    JSVenu

  30. #30

    Thread Starter
    Hyperactive Member
    Join Date
    Apr 2015
    Posts
    356

    Re: internals of activex exe buit in CreateObject multithreading vs CreateThread api

    Quote Originally Posted by The trick View Post
    CoRegisterGetClassObject registers the class factory (already created by runtime). CreateObject calls CoCreateInstance which calls IClassFactory::CreateInstance. This function creates a thread (if need) and creates an instance in that thread then it marshals the reference to the caller thread.
    CreateThread is called by runtime.
    Dear Trick,

    This is what I wanted to do by explicitly using CreateThread so that I can init runtime of my ThreadProc instead of using CreateObject directly in activex exe running in standalone mode.

    regards,
    JSVenu

  31. #31

  32. #32

    Thread Starter
    Hyperactive Member
    Join Date
    Apr 2015
    Posts
    356

    Re: internals of activex exe buit in CreateObject multithreading vs CreateThread api

    Quote Originally Posted by The trick View Post
    Why?
    Dear Trick,

    This is the reason I started this thread with the said title so that I can use CreateThread API and init runtime of my threadproc even in activex exe running in standalone mode with Thread per object or Thread pool >1 since I already can do init of threadproc in std exe and actx dll using CreateThread and also init runtime for actx exe with thread pool =1 like std exe with the exception of running with admin privileges for the first time.

    regards,
    JSVenu

  33. #33
    PowerPoster
    Join Date
    Feb 2015
    Posts
    2,687

    Re: internals of activex exe buit in CreateObject multithreading vs CreateThread api

    This is the example how to init ActiveX EXE thread:
    Code:
    Option Explicit
    
    ' // Lazy GUID structure
    Private Type tCurGUID
        c1          As Currency
        c2          As Currency
    End Type
    
    Public Declare Function CreateThread Lib "kernel32" ( _
                            ByRef lpThreadAttributes As Any, _
                            ByVal dwStackSize As Long, _
                            ByVal lpStartAddress As Long, _
                            ByRef lpParameter As Any, _
                            ByVal dwCreationFlags As Long, _
                            ByRef lpThreadId As Long) As Long
    Private Declare Function CreateIExprSrvObj Lib "MSVBVM60.DLL" ( _
                             ByVal pUnk1 As Long, _
                             ByVal lUnk2 As Long, _
                             ByVal pUnk3 As Long) As IUnknown
    Private Declare Function VBDllGetClassObject Lib "MSVBVM60.DLL" ( _
                             ByRef phModule As Long, _
                             ByVal lReserved As Long, _
                             ByVal pVbHeader As Long, _
                             ByRef pClsid As Any, _
                             ByRef pIID As Any, _
                             ByRef pObject As Any) As Long
    Private Declare Function GetMem4 Lib "msvbvm60" ( _
                             ByRef pSrc As Any, _
                             ByRef pDst As Any) As Long
    Private Declare Function CoInitialize Lib "ole32" ( _
                             ByRef pvReserved As Any) As Long
    Private Declare Sub CoUninitialize Lib "ole32" ()
    Private Declare Function GetModuleHandle Lib "kernel32" _
                             Alias "GetModuleHandleW" ( _
                             ByVal lpModuleName As Long) As Long
    
    Public g_hModule    As Long
    Public g_pVbHeader  As Long
    
    Sub Main()
        ' // No error checking
        g_hModule = App.hInstance
        g_pVbHeader = GetVBHeader()
        frmThread.Show vbModal  ' // To avoid msgloop
    End Sub
    
    Public Function ThreadProc( _
                    ByVal pVbHdr As Long) As Long
        Dim cExpSrv As IUnknown
        Dim tClsId  As tCurGUID
        Dim tIID    As tCurGUID
        
        Set cExpSrv = CreateIExprSrvObj(0, 4, 0)
        
        CoInitialize ByVal 0&
        
        tIID.c2 = 504403158265495.5712@
        
        VBDllGetClassObject GetModuleHandle(0), 0, pVbHdr, tClsId, tIID, 0
        
        CoUninitialize
        
    End Function
    
    Private Function GetVBHeader() As Long
        Dim ptr     As Long
       
        ' // Get e_lfanew
        GetMem4 ByVal g_hModule + &H3C, ptr
        ' // Get AddressOfEntryPoint
        GetMem4 ByVal ptr + &H28 + g_hModule, ptr
        ' // Get VBHeader
        GetMem4 ByVal ptr + g_hModule + 1, GetVBHeader
        
    End Function
    To create a thread:
    Code:
    CreateThread ByVal 0&, 0, AddressOf ThreadProc, ByVal g_pVbHeader, 0, 0
    Attached Files Attached Files

  34. #34

    Thread Starter
    Hyperactive Member
    Join Date
    Apr 2015
    Posts
    356

    Re: internals of activex exe buit in CreateObject multithreading vs CreateThread api

    Quote Originally Posted by The trick View Post
    This is the example how to init ActiveX EXE thread:
    Code:
    Option Explicit
    
    ' // Lazy GUID structure
    Private Type tCurGUID
        c1          As Currency
        c2          As Currency
    End Type
    
    Public Declare Function CreateThread Lib "kernel32" ( _
                            ByRef lpThreadAttributes As Any, _
                            ByVal dwStackSize As Long, _
                            ByVal lpStartAddress As Long, _
                            ByRef lpParameter As Any, _
                            ByVal dwCreationFlags As Long, _
                            ByRef lpThreadId As Long) As Long
    Private Declare Function CreateIExprSrvObj Lib "MSVBVM60.DLL" ( _
                             ByVal pUnk1 As Long, _
                             ByVal lUnk2 As Long, _
                             ByVal pUnk3 As Long) As IUnknown
    Private Declare Function VBDllGetClassObject Lib "MSVBVM60.DLL" ( _
                             ByRef phModule As Long, _
                             ByVal lReserved As Long, _
                             ByVal pVbHeader As Long, _
                             ByRef pClsid As Any, _
                             ByRef pIID As Any, _
                             ByRef pObject As Any) As Long
    Private Declare Function GetMem4 Lib "msvbvm60" ( _
                             ByRef pSrc As Any, _
                             ByRef pDst As Any) As Long
    Private Declare Function CoInitialize Lib "ole32" ( _
                             ByRef pvReserved As Any) As Long
    Private Declare Sub CoUninitialize Lib "ole32" ()
    Private Declare Function GetModuleHandle Lib "kernel32" _
                             Alias "GetModuleHandleW" ( _
                             ByVal lpModuleName As Long) As Long
    
    Public g_hModule    As Long
    Public g_pVbHeader  As Long
    
    Sub Main()
        ' // No error checking
        g_hModule = App.hInstance
        g_pVbHeader = GetVBHeader()
        frmThread.Show vbModal  ' // To avoid msgloop
    End Sub
    
    Public Function ThreadProc( _
                    ByVal pVbHdr As Long) As Long
        Dim cExpSrv As IUnknown
        Dim tClsId  As tCurGUID
        Dim tIID    As tCurGUID
        
        Set cExpSrv = CreateIExprSrvObj(0, 4, 0)
        
        CoInitialize ByVal 0&
        
        tIID.c2 = 504403158265495.5712@
        
        VBDllGetClassObject GetModuleHandle(0), 0, pVbHdr, tClsId, tIID, 0
        
        CoUninitialize
        
    End Function
    
    Private Function GetVBHeader() As Long
        Dim ptr     As Long
       
        ' // Get e_lfanew
        GetMem4 ByVal g_hModule + &H3C, ptr
        ' // Get AddressOfEntryPoint
        GetMem4 ByVal ptr + &H28 + g_hModule, ptr
        ' // Get VBHeader
        GetMem4 ByVal ptr + g_hModule + 1, GetVBHeader
        
    End Function
    To create a thread:
    Code:
    CreateThread ByVal 0&, 0, AddressOf ThreadProc, ByVal g_pVbHeader, 0, 0
    Dear Trick,

    First let me sincerely thankyou for the simple awesome example.
    I have run it in standalone mode.It worked perfect.
    The only doubt I have is you did not modify the vbheader as well as simply copied
    a vbheader to another vbheader just like by assignment vbhder2=vbhdr1 for using vbhdr2 as data in new thread.
    But you have made copy of vbheader in std exe using CreateVBHeaderCopy which was very complicated in the sense it had to take care of clearing of global variables.Please clarify.

    regards.
    JSVenu

  35. #35

  36. #36

    Thread Starter
    Hyperactive Member
    Join Date
    Apr 2015
    Posts
    356

    Re: internals of activex exe buit in CreateObject multithreading vs CreateThread api

    Quote Originally Posted by The trick View Post
    You don't need to modify the vbheader because it uses the apartment model so it doesn't clear the global/static variables of another project as in a stdexe.
    Dear Trick,

    OK without modifying the vbheader we can avoid reentracy in sub main using boolean variable.

    How does the application identify Thread per object or thread pool > 1 setting

    I am asking this since when we use thread pool = 1 setting we get following error in a msgbox :

    ---------------------------
    AxExeInitThread
    ---------------------------
    Run-time error '400':

    Form already displayed; can't show modally
    ---------------------------
    OK
    ---------------------------

    But when we use Thread per object or thread pool > 1 setting the application works fine without this error.
    How does the application identifies Thread per object or Thread Pool value.Is there any way to make this app work fine for any of this setting Thread per object or any Thread Pool value.

    regards,
    JSVenu
    Last edited by jsvenu; Apr 13th, 2020 at 11:38 AM.

  37. #37

  38. #38

    Thread Starter
    Hyperactive Member
    Join Date
    Apr 2015
    Posts
    356

    Re: internals of activex exe buit in CreateObject multithreading vs CreateThread api

    Dear Trick,

    OK I understood that we have to use new form instance each time.
    Only thing not understood is why we donot get the same error msg when we use Thread per object or Thread pool >1 when we use CreateThread api.For ex: if we use thread pool =2 we don't get it third time even without closing first two modal forms threads.

    regards,
    JSVenu
    Last edited by jsvenu; Apr 13th, 2020 at 01:00 PM.

  39. #39

    Thread Starter
    Hyperactive Member
    Join Date
    Apr 2015
    Posts
    356

    Re: internals of activex exe buit in CreateObject multithreading vs CreateThread api

    Dear Trick,

    When I try to bypass Sub Main in ThreadProc

    1. using g_bool global boolean variable and try to do something else in the thread after thread init as follows the code fails and every time Sub Main is being called:

    Code:
    public g_bool As Boolean       'fails
    Sub Main()
        
        ' // No error checking
        If (g_bool = False) Then         
        g_bool = True
        g_hModule = App.hInstance
        g_pVbHeader = GetVBHeader()
        frmThread.Show vbModal  ' // To avoid msgloop
        End If
    End Sub

    2. I even tried to modify local copy of vbheader in the thread to remove submain as follows but it was of no use.Please clarify.
    .
    Code:
    Public Function ThreadProc( _
                    ByVal pVbHdr As Long) As Long
        Dim cExpSrv As IUnknown
        Dim tClsId  As tCurGUID
        Dim tIID    As tCurGUID
        
        Set cExpSrv = CreateIExprSrvObj(0, 4, 0)
        
        CoInitialize ByVal 0&
        
        tIID.c2 = 504403158265495.5712@
        ModifyVBHeader pVbHdr                  'fails
        VBDllGetClassObject GetModuleHandle(0), 0, pVbHdr, tClsId, tIID, 0
        
        CoUninitialize
        
    End Function
    Where ModifyVBHeader sub is defined as follows:


    Code:
    ' // Modify VBHeader to remove Sub Main
    Public Sub ModifyVBHeader(mpVbHeader As Long)
        Dim ptr             As Long
        Dim lOldProtect     As Long
        Dim lFlags          As Long
        Dim lFormsCount     As Long
        Dim lModulesCount   As Long
        Dim lStructSize     As Long
        
        ' // Allow to write to that page
        VirtualProtect ByVal mpVbHeader, &H64, PAGE_EXECUTE_READWRITE, lOldProtect
        
        ' // Remove Sub Main
        ptr = mpVbHeader + &H2C
        GetMem4 0&, ByVal ptr
    
        VirtualProtect ByVal mpVbHeader, &H64, lOldProtect, 0
        
        ' // Remove startup form
        GetMem4 ByVal mpVbHeader + &H4C, ptr
        ' // Get number of forms
        GetMem2 ByVal mpVbHeader + &H44, lFormsCount
        
        Do While lFormsCount > 0
        
            ' // Get structure size
            GetMem4 ByVal ptr, lStructSize
            
            ' // Get flag (unknown5) from current form
            GetMem4 ByVal ptr + &H28, lFlags
            
            ' // When set, bit 5,
            If lFlags And &H10 Then
            
                ' // Unset bit 5
                lFlags = lFlags And &HFFFFFFEF
                ' // Are allowed to write in the page
                VirtualProtect ByVal ptr, 4, PAGE_EXECUTE_READWRITE, lOldProtect
                ' // Write changet lFlags
                GetMem4 lFlags, ByVal ptr + &H28
                ' // Restoring the memory attributes
                VirtualProtect ByVal ptr, 4, lOldProtect, 0
                
            End If
            
            lFormsCount = lFormsCount - 1
            ptr = ptr + lStructSize
            
        Loop
    
    End Sub
    Other than using FindWindow api (since using FindWindow api we can stop form display thru its hwnd if it is already displayed first time but not sub main) can you please suggest some way to bypass Sub main in my ThreadProc so that I can do something in my ThreadProc after vbdllgetclassobject call.


    regards,
    JSVenu
    Last edited by jsvenu; Apr 14th, 2020 at 07:18 AM.

  40. #40

Page 1 of 2 12 LastLast

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts
  •  



Click Here to Expand Forum to Full Width