Page 1 of 5 1234 ... LastLast
Results 1 to 40 of 172

Thread: using VbTrickThreading-master examples without the typelibs for Callback and Marshal

  1. #1

    Thread Starter
    Hyperactive Member
    Join Date
    Apr 2015
    Posts
    356

    using VbTrickThreading-master examples without the typelibs for Callback and Marshal

    Dear Trick,

    In the Callback demo of VbTrickThreading-master I have directly called the APIs and other data present in import.tlb which are being accessed in callback.dll by writing their declares and types and avoided it by unchecking import.tlb in project references.Now when I run the callbacktest.exe in compiled mode I get nothing displayed in log window and the application hangs and I had to close it using task manager.I am attaching the modified callback sample.

    1.Please clarify what are the modifications in addition I have to make it to work without import tlb just as it was running before when we were using import.tlb.


    2.Similarly can you provide me the code to directly make MarshalUserInterface example to work without using user_typelib.tlb type library.

    regards,
    JSVenu
    Attached Files Attached Files

  2. #2
    PowerPoster wqweto's Avatar
    Join Date
    May 2011
    Location
    Sofia, Bulgaria
    Posts
    6,167

    Re: using VbTrickThreading-master examples without the typelibs for Callback and Mar

    Quote Originally Posted by jsvenu View Post
    1.Please clarify what are the modifications in addition I have to make it to work without import tlb just as it was running before when we were using import.tlb.
    For each API declare VB6 compiler generates a small function that loads the dll, finds the entry point by name/ordinal, converts params ANSI<->Unicode and then calls the function. Finally after the call is executed it checks the stack for mismatches (wrong number of parameters) and sets Err.LastDllError from GetlastError API. In threading scenarios this last step fails if the VB6 runtime (which includes the Err object among other thigs) is not initialized on the running thread.

    Using typelib APIs does *not* set Err.LastDllError after calling the entry point, *unless* specifically instructed w/ the usesgetlasterror attribute in the IDL declaration.

    cheers,
    </wqw>

  3. #3
    PowerPoster
    Join Date
    Feb 2015
    Posts
    2,797

    Re: using VbTrickThreading-master examples without the typelibs for Callback and Mar

    You can't use an arbitrary code if you don't initialize the DLL-project-context, particularly the API calls declared in VB6.
    The proper way is to call DLLGetClassObject and then to call the exported functions when you use the ActiveX Dll project type.
    I had the thoughts to make the module which add the ability to initialize a context in DLL created as Standard EXE but there are some pitfalls like when you receive DLL_PROCESS_DETACH how you uninitialize the projects-context created in the other threads.

    The attached archive contains the module and several examples of usage in 3 different languages (VB6, C, PureBasic):
    • Simple - just show message box in DLL;
    • ShowForm - show the Form from DLL;
    • CallbackThread - create a thread in DLL and then call the callback function in EXE.


    Because of the code module is quite raw one i don't publish it in the CodeBank:

    Code:
    ' //
    ' // modDllInitialize.bas - The module provides support for runtime-initization for dynamic link libraries
    ' // Version 2
    ' // © Krivous Anatoly Anatolevich (The trick), 2015-2020
    ' // If you want to use additional callback from DllMain use DLL_USE_DLLMAIN conditional compilation adrgument
    ' // with the DllEntry callback function
    ' //
    
    Option Explicit
    
    Private Const PAGE_EXECUTE_READWRITE    As Long = &H40&
    Private Const FADF_AUTO                 As Long = 1
    Private Const VB_MAGIC                  As Long = &H21354256
    Private Const HEAP_ZERO_MEMORY          As Long = &H8
    Private Const HEAP_NO_SERIALIZE         As Long = &H1
    Private Const TLS_OUT_OF_INDEXES        As Long = &HFFFF&
    
    ' // Lazy GUID structure
    Private Type tCurGUID
        c1          As Currency
        c2          As Currency
    End Type
    
    Private Type SAFEARRAYBOUND
        cElements   As Long
        lLbound     As Long
    End Type
    
    Private Type SAFEARRAY
        cDims       As Integer
        fFeatures   As Integer
        cbElements  As Long
        cLocks      As Long
        pvData      As Long
        Bounds      As SAFEARRAYBOUND
    End Type
    
    Private Type tVBHeaderString
        pNames(3)   As Long
    End Type
    
    Private Const DLL_PROCESS_ATTACH    As Long = 1
    Private Const DLL_PROCESS_DETACH    As Long = 0
    Private Const DLL_THREAD_ATTACH     As Long = 2
    Private Const DLL_THREAD_DETACH     As Long = 3
    
    Private mlTlsSlot   As Long     ' // Index of the item in the TLS. There will be data specific to the thread.
    Private mpVbHeader  As Long     ' // Pointer to VBHeader structure.
    Private mhInstance  As Long     ' // Base address of the module
    
    ' // Unused
    Private Sub Main()
    
    End Sub
    
    ' // This function is called when the module is being loaded/unloaded to a process or a thread is created/destroyed
    Public Function DllMain( _
                    ByVal hinstDLL As Long, _
                    ByVal fdwReason As Long, _
                    ByVal lpvReserved As Long) As Long
    
        Select Case fdwReason
        Case DLL_PROCESS_ATTACH
            
            If VBDll.UserDllMain(mhInstance, 0, hinstDLL, fdwReason, lpvReserved) = 0 Then
                GoTo CleanUp
            End If
    
            mlTlsSlot = VBDll.TlsAlloc()
            If mlTlsSlot = TLS_OUT_OF_INDEXES Then GoTo CleanUp
            
            DllMain = InitializeRuntimeForProject(hinstDLL, True) And 1
            
    #If DLL_USE_DLLMAIN Then
            If DllMain Then
                DllMain = DllEntry(hinstDLL, fdwReason, lpvReserved)
            End If
    #End If
    
        Case DLL_THREAD_ATTACH
    
            If VBDll.UserDllMain(mhInstance, 0, hinstDLL, fdwReason, lpvReserved) = 0 Then
                GoTo CleanUp
            End If
    
            DllMain = InitializeRuntimeForProject(hinstDLL, False) And 1
    
    #If DLL_USE_DLLMAIN Then
            If DllMain Then
                DllMain = DllEntry(hinstDLL, fdwReason, lpvReserved)
            End If
    #End If
    
        Case DLL_THREAD_DETACH
    
    #If DLL_USE_DLLMAIN Then
            DllEntry hinstDLL, fdwReason, lpvReserved
    #End If
    
            If VBDll.UserDllMain(mhInstance, 0, hinstDLL, fdwReason, lpvReserved) = 0 Then
                GoTo CleanUp
            End If
    
            UninitializeRuntimeForProject hinstDLL
            
            FreeHeaderForCurrentThread
            
            DllMain = 1
    
        Case DLL_PROCESS_DETACH
    
    #If DLL_USE_DLLMAIN Then
            DllEntry hinstDLL, fdwReason, lpvReserved
    #End If
            
            CanUnloadNowCall
    
            VBDll.UserDllMain mhInstance, 0, hinstDLL, fdwReason, lpvReserved
            
            FreeHeaderForCurrentThread
            
            VBDll.TlsFree mlTlsSlot
    
            mlTlsSlot = 0
            mpVbHeader = 0
            
            DllMain = 1
            
            Exit Function
            
        End Select
          
    CleanUp:
    
    End Function
    
    ' // Uninitialize the runime
    Public Function UninitializeRuntimeForProject( _
                    ByVal hInstance As Long) As Boolean
        Dim pNewHeader  As Long
        
        ' // Check if the module is initialized
        pNewHeader = VBDll.TlsGetValue(mlTlsSlot)
        If pNewHeader = 0 Then Exit Function
    
        VBDll.CoUninitialize
        
        UninitializeRuntimeForProject = True
        
    End Function
    
    ' // Free the current header
    Public Function FreeHeaderForCurrentThread() As Boolean
        Dim pNewHeader  As Long
        
        ' // Check if the module is initialized
        pNewHeader = VBDll.TlsGetValue(mlTlsSlot)
        If pNewHeader = 0 Then Exit Function
        
        VBDll.HeapFree VBDll.GetProcessHeap(), 0, pNewHeader
        
    End Function
    
    ' // Initilaize the runtime
    Public Function InitializeRuntimeForProject( _
                    ByVal hInstance As Long, _
                    ByVal bIsFirst As Boolean) As Boolean
        Dim pNewHeader  As Long
        Dim tClsId      As tCurGUID
        Dim tIID        As tCurGUID
        Dim lUnused     As Long
        
        pNewHeader = VBDll.TlsGetValue(mlTlsSlot)
        
        ' // Check if the module already initialized
        If pNewHeader Then
    
            InitializeRuntimeForProject = True
            Exit Function
            
        End If
        
        VBDll.CoInitialize ByVal 0&
        
        If mpVbHeader = 0 Then
            
            ' // Search for VBHeader (EXEPROJECTINFO)
            mpVbHeader = SearchForVbHeader(hInstance)
            If mpVbHeader = 0 Then Exit Function
            
            ' // Modify header
            ModifyVBHeader
            
        End If
        
        ' // Create the new copy of headers for new instance
        pNewHeader = CreateVBHeaderCopy()
        
        ' // Save it
        VBDll.TlsSetValue mlTlsSlot, ByVal pNewHeader
    
        If pNewHeader = 0 Then
            Exit Function
        End If
        
        ' // IID_IUnknown
        tIID.c2 = 504403158265495.5712@
        
        ' // Call CThreadPool::InitDllAccess
        VBDll.VBDllGetClassObject hInstance, 0, pNewHeader, tClsId, tIID, 0
        
        If bIsFirst Then
            ' // Initialize App object
            lUnused = App.ThreadID
        End If
        
        InitializeRuntimeForProject = True
        
    End Function
    
    Private Sub CanUnloadNowCall()
        Dim pNewHeader  As Long
        Dim bThreading  As Byte
        
        ' // Check if the module is initialized
        pNewHeader = VBDll.TlsGetValue(mlTlsSlot)
        If pNewHeader = 0 Then Exit Sub
    
        ' // To ensure cleaning of the project data set the threading model to the apartment one.
        VBDll.GetMem1 ByVal pNewHeader + &H3C, bThreading
        bThreading = bThreading Or 1
        VBDll.GetMem1 bThreading, ByVal pNewHeader + &H3C
        
        ' // The runtime will call CThreadPool::CheckForProjectUnload and CVBThreadAction::CleanupProjData
        If VBDll.VBDllCanUnloadNow(pNewHeader) Then
            Exit Sub
        End If
    
    End Sub
    
    ' // Search for VBHeader(EXEPROJECTINFO)
    Private Function SearchForVbHeader( _
                     ByVal hInstance As Long) As Long
        Dim ptr             As Long
        Dim lSignature      As Long
        Dim pImportDesc     As Long
        Dim pStartSearch    As Long
        Dim pEndSearch      As Long
        Dim bData()         As Byte
        Dim tArrDesc        As SAFEARRAY
        Dim lIndex          As Long
        
        ' // VBHeader is placed within the end of IAT and beginning of IMAGE_IMPORT_DESCRIPTOR
        
        ' // Get e_lfanew
        VBDll.GetMem4 ByVal hInstance + &H3C, ptr
        ' // Get IAT
        VBDll.GetMem4 ByVal ptr + &H80 + hInstance, pImportDesc
        
        pEndSearch = hInstance + pImportDesc - 4
        
        Do
        
            ' // Get IMAGE_IMPORT_DESCRIPTOR.FirstThunk
            VBDll.GetMem4 ByVal pImportDesc + &H10 + hInstance, ptr
            
            If ptr > pStartSearch Then
                pStartSearch = ptr
            End If
            
            pImportDesc = pImportDesc + &H14
            
        Loop While ptr
        
        ' // Search for null-thunk (skip valid IAT entries)
        Do
            
            VBDll.GetMem4 ByVal hInstance + pStartSearch, ptr
            pStartSearch = pStartSearch + 4
            
        Loop While ptr
        
        pStartSearch = pStartSearch + hInstance
        
        If pEndSearch < pStartSearch Then Exit Function
        
        ' // Map the array to the data
        tArrDesc.cbElements = 1
        tArrDesc.cDims = 1
        tArrDesc.fFeatures = FADF_AUTO
        tArrDesc.pvData = pStartSearch
        tArrDesc.Bounds.cElements = pEndSearch - pStartSearch + 5
        
        VBDll.MoveArray bData(), VarPtr(tArrDesc)
        
        For lIndex = 0 To tArrDesc.Bounds.cElements - 5
            
            ' // __vbaS of an exe module has the following structure:
            ' // PUSH OFFSET VbHeader
            ' // CALL ThunRTMain
            
            ' // Search for PUSH IMM opcode
            If bData(lIndex) = &H68 Then
                
                ' // Get Immediate value
                VBDll.GetMem4 bData(lIndex + 1), ptr
                
                ' // Check range
                If ptr >= pStartSearch And ptr < pEndSearch Then
                    
                    ' // Check signature (VB5!)
                    VBDll.GetMem4 ByVal ptr, lSignature
                    
                    If lSignature = VB_MAGIC Then
                        
                        SearchForVbHeader = ptr
                        Exit Function
                        
                    End If
                    
                End If
                
            End If
            
        Next
        
    End Function
    
    ' // Modify VBHeader to replace Sub Main
    Private Sub ModifyVBHeader()
        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
        VBDll.VirtualProtect ByVal mpVbHeader, &H64, PAGE_EXECUTE_READWRITE, lOldProtect
        
        ' // Remove Sub Main
        ptr = mpVbHeader + &H2C
        VBDll.GetMem4 0&, ByVal ptr
    
        VBDll.VirtualProtect ByVal mpVbHeader, &H64, lOldProtect, 0
        
        ' // Remove startup form
        VBDll.GetMem4 ByVal mpVbHeader + &H4C, ptr
        ' // Get number of forms
        VBDll.GetMem2 ByVal mpVbHeader + &H44, lFormsCount
        
        Do While lFormsCount > 0
        
            ' // Get structure size
            VBDll.GetMem4 ByVal ptr, lStructSize
            
            ' // Get flag (unknown5) from current form
            VBDll.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
                VBDll.VirtualProtect ByVal ptr, 4, PAGE_EXECUTE_READWRITE, lOldProtect
                ' // Write changet lFlags
                VBDll.GetMem4 lFlags, ByVal ptr + &H28
                ' // Restoring the memory attributes
                VBDll.VirtualProtect ByVal ptr, 4, lOldProtect, 0
                
            End If
            
            lFormsCount = lFormsCount - 1
            ptr = ptr + lStructSize
            
        Loop
    
    End Sub
    
    ' // Create copy of VBHeader and other structures
    Private Function CreateVBHeaderCopy() As Long
        Dim pHeader         As Long
        Dim pOldProjInfo    As Long
        Dim pProjInfo       As Long
        Dim pObjTable       As Long
        Dim pOldObjTable    As Long
        Dim lDifference     As Long
        Dim lIndex          As Long
        Dim lSubIndex       As Long
        Dim tNames          As tVBHeaderString
        Dim lModulesCount   As Long
        Dim pDescriptors    As Long
        Dim pOldDesc        As Long
        Dim pVarBlock       As Long
        Dim lSizeOfHeaders  As Long
        Dim lExtCount       As Long
        Dim lNewExtCount    As Long
        Dim pOldExtApi      As Long
        Dim pExtApi         As Long
        Dim lExtFlags       As Long
    
        ' // Get size of all headers
        lSizeOfHeaders = &H6A + &H23C + &H54 + &HC
        
        VBDll.GetMem4 ByVal mpVbHeader + &H30, pOldProjInfo
        VBDll.GetMem4 ByVal pOldProjInfo + &H4, pOldObjTable
        VBDll.GetMem4 ByVal pOldObjTable + &H30, pOldDesc
        VBDll.GetMem2 ByVal pOldObjTable + &H2A, lModulesCount
        
        lSizeOfHeaders = lSizeOfHeaders + &H30 * lModulesCount
        
        ' // Free API external block
        VBDll.GetMem4 ByVal pOldProjInfo + &H238, lExtCount
        VBDll.GetMem4 ByVal pOldProjInfo + &H234, pOldExtApi
        
        For lIndex = 0 To lExtCount - 1
            
            VBDll.GetMem4 ByVal pOldExtApi + lIndex * 8, lExtFlags
            
            If lExtFlags <> 7 Then
                lNewExtCount = lNewExtCount + 1
            End If
            
        Next
        
        lSizeOfHeaders = lSizeOfHeaders + lNewExtCount * 8
                    
        ' // Allocate memory for header
        pHeader = VBDll.HeapAlloc(VBDll.GetProcessHeap(), HEAP_ZERO_MEMORY, lSizeOfHeaders)
        If pHeader = 0 Then GoTo CleanUp
    
        lDifference = pHeader - mpVbHeader
        
        VBDll.CopyMemory ByVal pHeader, ByVal mpVbHeader, &H6A
        
        ' // Update strings offsets
        VBDll.CopyMemory tNames.pNames(0), ByVal mpVbHeader + &H58, &H10
        
        For lIndex = 0 To 3
            tNames.pNames(lIndex) = tNames.pNames(lIndex) - lDifference
        Next
            
        VBDll.CopyMemory ByVal pHeader + &H58, tNames.pNames(0), &H10
    
        ' // In order to keep global variables
        ' // Change the VbPublicObjectDescriptor.lpPublicBytes, VbPublicObjectDescriptor.lpStaticBytes
        pProjInfo = pHeader + &H6A
    
        VBDll.CopyMemory ByVal pProjInfo, ByVal pOldProjInfo, &H23C
    
        ' // Update on VBHeader
        VBDll.GetMem4 pProjInfo, ByVal pHeader + &H30
    
        ' // Create copy of Object table
        pObjTable = pProjInfo + &H23C
    
        VBDll.CopyMemory ByVal pObjTable, ByVal pOldObjTable, &H54
    
        ' // Update
        VBDll.GetMem4 pObjTable, ByVal pProjInfo + &H4
    
        ' // Allocate descriptors
        pDescriptors = pObjTable + &H54
    
        VBDll.CopyMemory ByVal pDescriptors, ByVal pOldDesc, lModulesCount * &H30
    
        ' // Update
        VBDll.GetMem4 pDescriptors, ByVal pObjTable + &H30
    
        ' // Allocate variables block
        pVarBlock = pDescriptors + lModulesCount * &H30
    
        For lIndex = 0 To lModulesCount - 1
    
            ' // Zero number of public and local variables
            VBDll.GetMem4 pVarBlock, ByVal pDescriptors + lIndex * &H30 + &H8
            VBDll.GetMem4 0&, ByVal pDescriptors + lIndex * &H30 + &HC
    
        Next
        
        ' // Free API
        pExtApi = pVarBlock + &HC
        lSubIndex = 0
        
        For lIndex = 0 To lExtCount - 1
            
            VBDll.GetMem4 ByVal pOldExtApi + lIndex * 8, lExtFlags
            
            If lExtFlags <> 7 Then
                
                VBDll.GetMem8 ByVal pOldExtApi + lIndex * 8, ByVal pExtApi + lSubIndex * 8
                lSubIndex = lSubIndex + 1
                
            End If
            
        Next
        
        ' // Update
        VBDll.GetMem4 pExtApi, ByVal pProjInfo + &H234
        VBDll.GetMem4 lNewExtCount, ByVal pProjInfo + &H238
        
        CreateVBHeaderCopy = pHeader
        
    CleanUp:
    
    End Function
    Usage in C:

    Code:
    #include <windows.h>
    #include <stdio.h>
    #include <stdlib.h>
    #include <time.h>
    #include <initguid.h>
    
    #include "interfaces.h"
    
    volatile DWORD g_TlsSlot;
    
    LONG __stdcall CallBack(IUnknown *pObj) {
    	HRESULT hr;
    
    	_Form *pForm;
    	float fWidth, fHeight;
    
    	if (FAILED(hr = pObj->lpVtbl->QueryInterface(pObj, &IID__Form, (void**)&pForm))) {
    		return E_UNEXPECTED;
    	}
    
    	// Check if already initialized
    	if (!TlsGetValue(g_TlsSlot)) {
    		TlsSetValue(g_TlsSlot, (LPVOID)1);
    		srand(time(NULL));
    	}
    
    	if (SUCCEEDED(hr = pForm->lpVtbl->get_ScaleWidth(pForm, &fWidth)) &&
    		SUCCEEDED(hr = pForm->lpVtbl->get_ScaleHeight(pForm, &fHeight))) {
    		hr = pForm->lpVtbl->Circle(pForm, 0, rand() % (int)fWidth, rand() % (int)fHeight, rand() % 500, 0, 0, 0, 0);
    	}
    
    	pForm->lpVtbl->Release(pForm);
    
    	return hr;
    
    }
    
    int main(int argc, char **argv) {
    	HINSTANCE hLib = LoadLibrary("CallbackThread.dll");
    	DWORD g_TlsSlot = TlsAlloc();
    
    	VOID (__stdcall *SetCallback)(LONG (__stdcall *)(IUnknown *)) = 
    		(VOID (__stdcall *)(LONG (__stdcall *)(IUnknown *)))GetProcAddress(hLib, "SetCallback");
    
    	if (!SetCallback)
    		return 1;
    
    	SetCallback(CallBack);
    
    	printf("press a button to exit\r\n");
    	getchar();
    
    	FreeLibrary(hLib);
    	TlsFree(g_TlsSlot);
    
    	return 0;
    
    }
    Attached Files Attached Files

  4. #4

    Thread Starter
    Hyperactive Member
    Join Date
    Apr 2015
    Posts
    356

    Re: using VbTrickThreading-master examples without the typelibs for Callback and Mar

    Quote Originally Posted by The trick View Post
    You can't use an arbitrary code if you don't initialize the DLL-project-context, particularly the API calls declared in VB6.
    The proper way is to call DLLGetClassObject and then to call the exported functions when you use the ActiveX Dll project type.
    I had the thoughts to make the module which add the ability to initialize a context in DLL created as Standard EXE but there are some pitfalls like when you receive DLL_PROCESS_DETACH how you uninitialize the projects-context created in the other threads.

    The attached archive contains the module and several examples of usage in 3 different languages (VB6, C, PureBasic):
    • Simple - just show message box in DLL;
    • ShowForm - show the Form from DLL;
    • CallbackThread - create a thread in DLL and then call the callback function in EXE.


    Because of the code module is quite raw one i don't publish it in the CodeBank:

    Code:
    ' //
    ' // modDllInitialize.bas - The module provides support for runtime-initization for dynamic link libraries
    ' // Version 2
    ' // © Krivous Anatoly Anatolevich (The trick), 2015-2020
    ' // If you want to use additional callback from DllMain use DLL_USE_DLLMAIN conditional compilation adrgument
    ' // with the DllEntry callback function
    ' //
    
    Option Explicit
    
    Private Const PAGE_EXECUTE_READWRITE    As Long = &H40&
    Private Const FADF_AUTO                 As Long = 1
    Private Const VB_MAGIC                  As Long = &H21354256
    Private Const HEAP_ZERO_MEMORY          As Long = &H8
    Private Const HEAP_NO_SERIALIZE         As Long = &H1
    Private Const TLS_OUT_OF_INDEXES        As Long = &HFFFF&
    
    ' // Lazy GUID structure
    Private Type tCurGUID
        c1          As Currency
        c2          As Currency
    End Type
    
    Private Type SAFEARRAYBOUND
        cElements   As Long
        lLbound     As Long
    End Type
    
    Private Type SAFEARRAY
        cDims       As Integer
        fFeatures   As Integer
        cbElements  As Long
        cLocks      As Long
        pvData      As Long
        Bounds      As SAFEARRAYBOUND
    End Type
    
    Private Type tVBHeaderString
        pNames(3)   As Long
    End Type
    
    Private Const DLL_PROCESS_ATTACH    As Long = 1
    Private Const DLL_PROCESS_DETACH    As Long = 0
    Private Const DLL_THREAD_ATTACH     As Long = 2
    Private Const DLL_THREAD_DETACH     As Long = 3
    
    Private mlTlsSlot   As Long     ' // Index of the item in the TLS. There will be data specific to the thread.
    Private mpVbHeader  As Long     ' // Pointer to VBHeader structure.
    Private mhInstance  As Long     ' // Base address of the module
    
    ' // Unused
    Private Sub Main()
    
    End Sub
    
    ' // This function is called when the module is being loaded/unloaded to a process or a thread is created/destroyed
    Public Function DllMain( _
                    ByVal hinstDLL As Long, _
                    ByVal fdwReason As Long, _
                    ByVal lpvReserved As Long) As Long
    
        Select Case fdwReason
        Case DLL_PROCESS_ATTACH
            
            If VBDll.UserDllMain(mhInstance, 0, hinstDLL, fdwReason, lpvReserved) = 0 Then
                GoTo CleanUp
            End If
    
            mlTlsSlot = VBDll.TlsAlloc()
            If mlTlsSlot = TLS_OUT_OF_INDEXES Then GoTo CleanUp
            
            DllMain = InitializeRuntimeForProject(hinstDLL, True) And 1
            
    #If DLL_USE_DLLMAIN Then
            If DllMain Then
                DllMain = DllEntry(hinstDLL, fdwReason, lpvReserved)
            End If
    #End If
    
        Case DLL_THREAD_ATTACH
    
            If VBDll.UserDllMain(mhInstance, 0, hinstDLL, fdwReason, lpvReserved) = 0 Then
                GoTo CleanUp
            End If
    
            DllMain = InitializeRuntimeForProject(hinstDLL, False) And 1
    
    #If DLL_USE_DLLMAIN Then
            If DllMain Then
                DllMain = DllEntry(hinstDLL, fdwReason, lpvReserved)
            End If
    #End If
    
        Case DLL_THREAD_DETACH
    
    #If DLL_USE_DLLMAIN Then
            DllEntry hinstDLL, fdwReason, lpvReserved
    #End If
    
            If VBDll.UserDllMain(mhInstance, 0, hinstDLL, fdwReason, lpvReserved) = 0 Then
                GoTo CleanUp
            End If
    
            UninitializeRuntimeForProject hinstDLL
            
            FreeHeaderForCurrentThread
            
            DllMain = 1
    
        Case DLL_PROCESS_DETACH
    
    #If DLL_USE_DLLMAIN Then
            DllEntry hinstDLL, fdwReason, lpvReserved
    #End If
            
            CanUnloadNowCall
    
            VBDll.UserDllMain mhInstance, 0, hinstDLL, fdwReason, lpvReserved
            
            FreeHeaderForCurrentThread
            
            VBDll.TlsFree mlTlsSlot
    
            mlTlsSlot = 0
            mpVbHeader = 0
            
            DllMain = 1
            
            Exit Function
            
        End Select
          
    CleanUp:
    
    End Function
    
    ' // Uninitialize the runime
    Public Function UninitializeRuntimeForProject( _
                    ByVal hInstance As Long) As Boolean
        Dim pNewHeader  As Long
        
        ' // Check if the module is initialized
        pNewHeader = VBDll.TlsGetValue(mlTlsSlot)
        If pNewHeader = 0 Then Exit Function
    
        VBDll.CoUninitialize
        
        UninitializeRuntimeForProject = True
        
    End Function
    
    ' // Free the current header
    Public Function FreeHeaderForCurrentThread() As Boolean
        Dim pNewHeader  As Long
        
        ' // Check if the module is initialized
        pNewHeader = VBDll.TlsGetValue(mlTlsSlot)
        If pNewHeader = 0 Then Exit Function
        
        VBDll.HeapFree VBDll.GetProcessHeap(), 0, pNewHeader
        
    End Function
    
    ' // Initilaize the runtime
    Public Function InitializeRuntimeForProject( _
                    ByVal hInstance As Long, _
                    ByVal bIsFirst As Boolean) As Boolean
        Dim pNewHeader  As Long
        Dim tClsId      As tCurGUID
        Dim tIID        As tCurGUID
        Dim lUnused     As Long
        
        pNewHeader = VBDll.TlsGetValue(mlTlsSlot)
        
        ' // Check if the module already initialized
        If pNewHeader Then
    
            InitializeRuntimeForProject = True
            Exit Function
            
        End If
        
        VBDll.CoInitialize ByVal 0&
        
        If mpVbHeader = 0 Then
            
            ' // Search for VBHeader (EXEPROJECTINFO)
            mpVbHeader = SearchForVbHeader(hInstance)
            If mpVbHeader = 0 Then Exit Function
            
            ' // Modify header
            ModifyVBHeader
            
        End If
        
        ' // Create the new copy of headers for new instance
        pNewHeader = CreateVBHeaderCopy()
        
        ' // Save it
        VBDll.TlsSetValue mlTlsSlot, ByVal pNewHeader
    
        If pNewHeader = 0 Then
            Exit Function
        End If
        
        ' // IID_IUnknown
        tIID.c2 = 504403158265495.5712@
        
        ' // Call CThreadPool::InitDllAccess
        VBDll.VBDllGetClassObject hInstance, 0, pNewHeader, tClsId, tIID, 0
        
        If bIsFirst Then
            ' // Initialize App object
            lUnused = App.ThreadID
        End If
        
        InitializeRuntimeForProject = True
        
    End Function
    
    Private Sub CanUnloadNowCall()
        Dim pNewHeader  As Long
        Dim bThreading  As Byte
        
        ' // Check if the module is initialized
        pNewHeader = VBDll.TlsGetValue(mlTlsSlot)
        If pNewHeader = 0 Then Exit Sub
    
        ' // To ensure cleaning of the project data set the threading model to the apartment one.
        VBDll.GetMem1 ByVal pNewHeader + &H3C, bThreading
        bThreading = bThreading Or 1
        VBDll.GetMem1 bThreading, ByVal pNewHeader + &H3C
        
        ' // The runtime will call CThreadPool::CheckForProjectUnload and CVBThreadAction::CleanupProjData
        If VBDll.VBDllCanUnloadNow(pNewHeader) Then
            Exit Sub
        End If
    
    End Sub
    
    ' // Search for VBHeader(EXEPROJECTINFO)
    Private Function SearchForVbHeader( _
                     ByVal hInstance As Long) As Long
        Dim ptr             As Long
        Dim lSignature      As Long
        Dim pImportDesc     As Long
        Dim pStartSearch    As Long
        Dim pEndSearch      As Long
        Dim bData()         As Byte
        Dim tArrDesc        As SAFEARRAY
        Dim lIndex          As Long
        
        ' // VBHeader is placed within the end of IAT and beginning of IMAGE_IMPORT_DESCRIPTOR
        
        ' // Get e_lfanew
        VBDll.GetMem4 ByVal hInstance + &H3C, ptr
        ' // Get IAT
        VBDll.GetMem4 ByVal ptr + &H80 + hInstance, pImportDesc
        
        pEndSearch = hInstance + pImportDesc - 4
        
        Do
        
            ' // Get IMAGE_IMPORT_DESCRIPTOR.FirstThunk
            VBDll.GetMem4 ByVal pImportDesc + &H10 + hInstance, ptr
            
            If ptr > pStartSearch Then
                pStartSearch = ptr
            End If
            
            pImportDesc = pImportDesc + &H14
            
        Loop While ptr
        
        ' // Search for null-thunk (skip valid IAT entries)
        Do
            
            VBDll.GetMem4 ByVal hInstance + pStartSearch, ptr
            pStartSearch = pStartSearch + 4
            
        Loop While ptr
        
        pStartSearch = pStartSearch + hInstance
        
        If pEndSearch < pStartSearch Then Exit Function
        
        ' // Map the array to the data
        tArrDesc.cbElements = 1
        tArrDesc.cDims = 1
        tArrDesc.fFeatures = FADF_AUTO
        tArrDesc.pvData = pStartSearch
        tArrDesc.Bounds.cElements = pEndSearch - pStartSearch + 5
        
        VBDll.MoveArray bData(), VarPtr(tArrDesc)
        
        For lIndex = 0 To tArrDesc.Bounds.cElements - 5
            
            ' // __vbaS of an exe module has the following structure:
            ' // PUSH OFFSET VbHeader
            ' // CALL ThunRTMain
            
            ' // Search for PUSH IMM opcode
            If bData(lIndex) = &H68 Then
                
                ' // Get Immediate value
                VBDll.GetMem4 bData(lIndex + 1), ptr
                
                ' // Check range
                If ptr >= pStartSearch And ptr < pEndSearch Then
                    
                    ' // Check signature (VB5!)
                    VBDll.GetMem4 ByVal ptr, lSignature
                    
                    If lSignature = VB_MAGIC Then
                        
                        SearchForVbHeader = ptr
                        Exit Function
                        
                    End If
                    
                End If
                
            End If
            
        Next
        
    End Function
    
    ' // Modify VBHeader to replace Sub Main
    Private Sub ModifyVBHeader()
        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
        VBDll.VirtualProtect ByVal mpVbHeader, &H64, PAGE_EXECUTE_READWRITE, lOldProtect
        
        ' // Remove Sub Main
        ptr = mpVbHeader + &H2C
        VBDll.GetMem4 0&, ByVal ptr
    
        VBDll.VirtualProtect ByVal mpVbHeader, &H64, lOldProtect, 0
        
        ' // Remove startup form
        VBDll.GetMem4 ByVal mpVbHeader + &H4C, ptr
        ' // Get number of forms
        VBDll.GetMem2 ByVal mpVbHeader + &H44, lFormsCount
        
        Do While lFormsCount > 0
        
            ' // Get structure size
            VBDll.GetMem4 ByVal ptr, lStructSize
            
            ' // Get flag (unknown5) from current form
            VBDll.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
                VBDll.VirtualProtect ByVal ptr, 4, PAGE_EXECUTE_READWRITE, lOldProtect
                ' // Write changet lFlags
                VBDll.GetMem4 lFlags, ByVal ptr + &H28
                ' // Restoring the memory attributes
                VBDll.VirtualProtect ByVal ptr, 4, lOldProtect, 0
                
            End If
            
            lFormsCount = lFormsCount - 1
            ptr = ptr + lStructSize
            
        Loop
    
    End Sub
    
    ' // Create copy of VBHeader and other structures
    Private Function CreateVBHeaderCopy() As Long
        Dim pHeader         As Long
        Dim pOldProjInfo    As Long
        Dim pProjInfo       As Long
        Dim pObjTable       As Long
        Dim pOldObjTable    As Long
        Dim lDifference     As Long
        Dim lIndex          As Long
        Dim lSubIndex       As Long
        Dim tNames          As tVBHeaderString
        Dim lModulesCount   As Long
        Dim pDescriptors    As Long
        Dim pOldDesc        As Long
        Dim pVarBlock       As Long
        Dim lSizeOfHeaders  As Long
        Dim lExtCount       As Long
        Dim lNewExtCount    As Long
        Dim pOldExtApi      As Long
        Dim pExtApi         As Long
        Dim lExtFlags       As Long
    
        ' // Get size of all headers
        lSizeOfHeaders = &H6A + &H23C + &H54 + &HC
        
        VBDll.GetMem4 ByVal mpVbHeader + &H30, pOldProjInfo
        VBDll.GetMem4 ByVal pOldProjInfo + &H4, pOldObjTable
        VBDll.GetMem4 ByVal pOldObjTable + &H30, pOldDesc
        VBDll.GetMem2 ByVal pOldObjTable + &H2A, lModulesCount
        
        lSizeOfHeaders = lSizeOfHeaders + &H30 * lModulesCount
        
        ' // Free API external block
        VBDll.GetMem4 ByVal pOldProjInfo + &H238, lExtCount
        VBDll.GetMem4 ByVal pOldProjInfo + &H234, pOldExtApi
        
        For lIndex = 0 To lExtCount - 1
            
            VBDll.GetMem4 ByVal pOldExtApi + lIndex * 8, lExtFlags
            
            If lExtFlags <> 7 Then
                lNewExtCount = lNewExtCount + 1
            End If
            
        Next
        
        lSizeOfHeaders = lSizeOfHeaders + lNewExtCount * 8
                    
        ' // Allocate memory for header
        pHeader = VBDll.HeapAlloc(VBDll.GetProcessHeap(), HEAP_ZERO_MEMORY, lSizeOfHeaders)
        If pHeader = 0 Then GoTo CleanUp
    
        lDifference = pHeader - mpVbHeader
        
        VBDll.CopyMemory ByVal pHeader, ByVal mpVbHeader, &H6A
        
        ' // Update strings offsets
        VBDll.CopyMemory tNames.pNames(0), ByVal mpVbHeader + &H58, &H10
        
        For lIndex = 0 To 3
            tNames.pNames(lIndex) = tNames.pNames(lIndex) - lDifference
        Next
            
        VBDll.CopyMemory ByVal pHeader + &H58, tNames.pNames(0), &H10
    
        ' // In order to keep global variables
        ' // Change the VbPublicObjectDescriptor.lpPublicBytes, VbPublicObjectDescriptor.lpStaticBytes
        pProjInfo = pHeader + &H6A
    
        VBDll.CopyMemory ByVal pProjInfo, ByVal pOldProjInfo, &H23C
    
        ' // Update on VBHeader
        VBDll.GetMem4 pProjInfo, ByVal pHeader + &H30
    
        ' // Create copy of Object table
        pObjTable = pProjInfo + &H23C
    
        VBDll.CopyMemory ByVal pObjTable, ByVal pOldObjTable, &H54
    
        ' // Update
        VBDll.GetMem4 pObjTable, ByVal pProjInfo + &H4
    
        ' // Allocate descriptors
        pDescriptors = pObjTable + &H54
    
        VBDll.CopyMemory ByVal pDescriptors, ByVal pOldDesc, lModulesCount * &H30
    
        ' // Update
        VBDll.GetMem4 pDescriptors, ByVal pObjTable + &H30
    
        ' // Allocate variables block
        pVarBlock = pDescriptors + lModulesCount * &H30
    
        For lIndex = 0 To lModulesCount - 1
    
            ' // Zero number of public and local variables
            VBDll.GetMem4 pVarBlock, ByVal pDescriptors + lIndex * &H30 + &H8
            VBDll.GetMem4 0&, ByVal pDescriptors + lIndex * &H30 + &HC
    
        Next
        
        ' // Free API
        pExtApi = pVarBlock + &HC
        lSubIndex = 0
        
        For lIndex = 0 To lExtCount - 1
            
            VBDll.GetMem4 ByVal pOldExtApi + lIndex * 8, lExtFlags
            
            If lExtFlags <> 7 Then
                
                VBDll.GetMem8 ByVal pOldExtApi + lIndex * 8, ByVal pExtApi + lSubIndex * 8
                lSubIndex = lSubIndex + 1
                
            End If
            
        Next
        
        ' // Update
        VBDll.GetMem4 pExtApi, ByVal pProjInfo + &H234
        VBDll.GetMem4 lNewExtCount, ByVal pProjInfo + &H238
        
        CreateVBHeaderCopy = pHeader
        
    CleanUp:
    
    End Function
    Usage in C:

    Code:
    #include <windows.h>
    #include <stdio.h>
    #include <stdlib.h>
    #include <time.h>
    #include <initguid.h>
    
    #include "interfaces.h"
    
    volatile DWORD g_TlsSlot;
    
    LONG __stdcall CallBack(IUnknown *pObj) {
    	HRESULT hr;
    
    	_Form *pForm;
    	float fWidth, fHeight;
    
    	if (FAILED(hr = pObj->lpVtbl->QueryInterface(pObj, &IID__Form, (void**)&pForm))) {
    		return E_UNEXPECTED;
    	}
    
    	// Check if already initialized
    	if (!TlsGetValue(g_TlsSlot)) {
    		TlsSetValue(g_TlsSlot, (LPVOID)1);
    		srand(time(NULL));
    	}
    
    	if (SUCCEEDED(hr = pForm->lpVtbl->get_ScaleWidth(pForm, &fWidth)) &&
    		SUCCEEDED(hr = pForm->lpVtbl->get_ScaleHeight(pForm, &fHeight))) {
    		hr = pForm->lpVtbl->Circle(pForm, 0, rand() % (int)fWidth, rand() % (int)fHeight, rand() % 500, 0, 0, 0, 0);
    	}
    
    	pForm->lpVtbl->Release(pForm);
    
    	return hr;
    
    }
    
    int main(int argc, char **argv) {
    	HINSTANCE hLib = LoadLibrary("CallbackThread.dll");
    	DWORD g_TlsSlot = TlsAlloc();
    
    	VOID (__stdcall *SetCallback)(LONG (__stdcall *)(IUnknown *)) = 
    		(VOID (__stdcall *)(LONG (__stdcall *)(IUnknown *)))GetProcAddress(hLib, "SetCallback");
    
    	if (!SetCallback)
    		return 1;
    
    	SetCallback(CallBack);
    
    	printf("press a button to exit\r\n");
    	getchar();
    
    	FreeLibrary(hLib);
    	TlsFree(g_TlsSlot);
    
    	return 0;
    
    }

    Dear Trick,

    Thankyou very much for the reply.

    1. I understand that if we convert the attachment (Callback.zip) I sent you can be first converted to activex dll which requires a multiuse class to be added to it by default for it to function.I already tried it like this but it was also giving the same problem like dll using standard exe already sent without type library.ie.,
    Callback demo is not working if we either use standard dll or activex dll without type library.
    Here we are using implicit linking using declare instead of explicit linking you showed in Graphics native dll example using LoadLibrary.

    2. The Release.zip example sent by you also uses VBDll.tlb.

    Is there any way to avoid type library and solve the above two cases and MarshalUserInterface demo also.
    Can __vbaS be of any help here.

    regards,
    JSVenu

  5. #5

    Thread Starter
    Hyperactive Member
    Join Date
    Apr 2015
    Posts
    356

    Re: using VbTrickThreading-master examples without the typelibs for Callback and Mar

    Quote Originally Posted by wqweto View Post
    For each API declare VB6 compiler generates a small function that loads the dll, finds the entry point by name/ordinal, converts params ANSI<->Unicode and then calls the function. Finally after the call is executed it checks the stack for mismatches (wrong number of parameters) and sets Err.LastDllError from GetlastError API. In threading scenarios this last step fails if the VB6 runtime (which includes the Err object among other thigs) is not initialized on the running thread.

    Using typelib APIs does *not* set Err.LastDllError after calling the entry point, *unless* specifically instructed w/ the usesgetlasterror attribute in the IDL declaration.

    cheers,
    </wqw>
    Dear wqw,
    Thankyou for the reply.
    regards,
    JSVenu

  6. #6

  7. #7

    Thread Starter
    Hyperactive Member
    Join Date
    Apr 2015
    Posts
    356

    Re: using VbTrickThreading-master examples without the typelibs for Callback and Mar

    Quote Originally Posted by The trick View Post
    I don't know what should i answer. I gave you example and wqweto explained why you can't avoid type libraries.
    Dear Trick,

    In Creation of native dll in code bank you have shown how to use loadlibrary and use import.tlb.I tried to replace the calls in import.tlb directly and have run GraphicsTestdll project without import tlb successfully.
    My question is when it is possible with loadlibrary ie., using explicit linking why it is not possible using declare or implicit linking.

    regards,
    JSVenu

  8. #8
    Fanatic Member
    Join Date
    Jun 2016
    Location
    España
    Posts
    630

    Re: using VbTrickThreading-master examples without the typelibs for Callback and Mar

    Trick Hi,

    your example modify it to make it work with a class module.
    but the only works returned class during that call, automatically closes the thread.
    and the object is deleted
    only it works with form, or can make a loop that does not close.

    in exe:
    Code:
    'plugin.cls
    Option Explicit
    Public cFrm    As Object
    Public Function ThreadProc_(ByVal pObj As Long) As Long
        Call InitCurrentThreadAndCallFunction(AddressOf ThreadProc, pObj, ThreadProc_)
    End Function
    
    Public Function ThreadProc( _
                    ByVal cObj As IUnknown) As Long
        Set cFrm = cObj
        cFrm.ThreadID
    End Function
    dll:
    Code:
    Private Const CC_STDCALL    As Long = 4
    
    Private Declare Function DispCallFunc Lib "oleaut32.dll" ( _
                             ByRef pvInstance As Any, _
                             ByVal oVft As Long, _
                             ByVal cc As Long, _
                             ByVal vtReturn As VbVarType, _
                             ByVal cActuals As Long, _
                             ByRef prgvt As Any, _
                             ByRef prgpvarg As Any, _
                             ByRef pvargResult As Variant) As Long
    
    Private mpfn    As Long
    
    Public Property Let Callback(ByVal lValue As Long)
        mpfn = lValue
        MsgBox DispCallFunc(ByVal 0&, mpfn, CC_STDCALL, vbEmpty, 1, vbDataObject, VarPtr(CVar(Me)), CVar(0))
    End Property
    
    Public Sub threadid()
        MsgBox App.threadid
    End Sub
    Code:
    'modMain
    Option Explicit
    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
    Public Declare Function CloseHandle Lib "kernel32" ( _
                            ByVal hObject As Long) As Long
    
    ' //
    ' // Create thread and create frmThread in that thread and set callback
    ' // function to pfn in that thread
    ' //
    Sub SetCallback( _
        ByVal pfn As Long)
            
        CloseHandle CreateThread(ByVal 0&, 0, AddressOf ThreadProc, ByVal pfn, 0, 0)
            
    End Sub
    
    Private Function ThreadProc( _
                    ByVal pfn As Long) As Long
        Dim cFrm    As plugin
        Set cFrm = New plugin
        cFrm.Callback = pfn
    End Function

    sorry I'm a little new to the multithreading issue
    Greetings

  9. #9

  10. #10
    Fanatic Member
    Join Date
    Jun 2016
    Location
    España
    Posts
    630

    Re: using VbTrickThreading-master examples without the typelibs for Callback and Mar

    I use your module in my project to load many dll without registration.
    and it works really well.
    https://pastebin.com/hPxJf4r4
    I could not find the post code sorry for this pastebin.

    as I use it in conjunction with your module multithreading.
    could you please make some example.
    sorry for bothering

  11. #11

  12. #12
    Fanatic Member
    Join Date
    Jun 2016
    Location
    España
    Posts
    630

    Re: using VbTrickThreading-master examples without the typelibs for Callback and Mar

    Sorry to express myself so badly.

    how to use the module "libraries without registration" that creates objects of the dll.
    and those dll do the multithreading.
    or if regfree multihreading objects can be created.
    because it is simpler to execute calls to objects than through apis.
    because it is easier to communicate between objects as well as through callback.
    or so I see it.

    greetings thank you for answering and for your work

  13. #13

    Thread Starter
    Hyperactive Member
    Join Date
    Apr 2015
    Posts
    356

    Re: using VbTrickThreading-master examples without the typelibs for Callback and Mar

    Quote Originally Posted by The trick View Post
    I don't know what should i answer. I gave you example and wqweto explained why you can't avoid type libraries.
    Dear Trick,

    Can you tell me how to find the instance handle of the dll which can be implicitly loaded into our exe without using LoadLibrary api .Then we can use that loaded instance of the dll and initialize runtime of the dll from our exe instead of doing the same from dll using dllmain.In this way typelibrary can be avoided.

    regards,
    JSVenu

  14. #14
    PowerPoster
    Join Date
    Feb 2015
    Posts
    2,797

    Re: using VbTrickThreading-master examples without the typelibs for Callback and Mar

    yokesee,
    The simplest method is to create a class in EXE which provides a object from external dll. Then you can use CreatePrivateObjectByNameInNewThread to create this object in its own apartments. I'll make example later.

    Can you tell me how to find the instance handle of the dll which can be implicitly loaded into our exe without using LoadLibrary api .Then we can use that loaded instance of the dll and initialize runtime of the dll from our exe instead of doing the same from dll using dllmain.In this way typelibrary can be avoided.
    This is bad approach to solve problem. I gave some hints how to do it with and without tlb.

  15. #15
    PowerPoster wqweto's Avatar
    Join Date
    May 2011
    Location
    Sofia, Bulgaria
    Posts
    6,167

    Re: using VbTrickThreading-master examples without the typelibs for Callback and Mar

    @The trick (mailbox quota exceeded)

    RE: jsvenu user

    Hi,

    I'm suspecting this guy is a malware creator wannabe and I already reported him based on the research he is doing.

    Just use Add to Ignore List from his profile or at least try *not* to help him weaponize whatever rootkits/resources he is fantasizing to hide from anti-virus apps.

    cheers,
    </wqw>

  16. #16

    Thread Starter
    Hyperactive Member
    Join Date
    Apr 2015
    Posts
    356

    Re: using VbTrickThreading-master examples without the typelibs for Callback and Mar

    Quote Originally Posted by The trick View Post
    This is bad approach to solve problem. I gave some hints how to do it with and without tlb.
    Dear Trick,

    You already said in http://www.vbforums.com/showthread.p...n-standard-dll post #19 as follows

    Re: initializing runtime in standard dll
    You can initialize the runtime in the DLLMain as well but that isn't good approach. Just make an exported function which initializes the runtime and just call it after LoadLibrary.
    Can you tell me hints on how to do without tlb.

    regards,
    JSVenu

  17. #17

  18. #18
    Fanatic Member
    Join Date
    Jun 2016
    Location
    España
    Posts
    630

    Re: using VbTrickThreading-master examples without the typelibs for Callback and Mar

    Quote Originally Posted by The trick View Post
    yokesee,
    The simplest method is to create a class in EXE which provides a object from external dll. Then you can use CreatePrivateObjectByNameInNewThread to create this object in its own apartments. I'll make example later.
    Yes please
    Thanks a lot

  19. #19

    Thread Starter
    Hyperactive Member
    Join Date
    Apr 2015
    Posts
    356

    Re: using VbTrickThreading-master examples without the typelibs for Callback and Mar

    Quote Originally Posted by wqweto View Post
    @The trick (mailbox quota exceeded)

    RE: jsvenu user

    Hi,

    I'm suspecting this guy is a malware creator wannabe and I already reported him based on the research he is doing.

    Just use Add to Ignore List from his profile or at least try *not* to help him weaponize whatever rootkits/resources he is fantasizing to hide from anti-virus apps.

    cheers,
    </wqw>
    Dear wqw,

    Already in the discussion of http://www.vbforums.com/showthread.p...n-standard-dll
    Trick has given example of InitProjectContextDll of initializing project context of dll thru exe without tlb.
    But here he uses LoadLibrary.No malware here as you think.I am trying to use vb6 code directly instead of using a tlb for apis .

    regards,
    JSVenu

  20. #20

    Thread Starter
    Hyperactive Member
    Join Date
    Apr 2015
    Posts
    356

    Re: using VbTrickThreading-master examples without the typelibs for Callback and Mar

    Dear Trick and Wqewto,

    Wqewto's quote:
    For each API declare VB6 compiler generates a small function that loads the dll, finds the entry point by name/ordinal, converts params ANSI<->Unicode and then calls the function. Finally after the call is executed it checks the stack for mismatches (wrong number of parameters) and sets Err.LastDllError from GetlastError API. In threading scenarios this last step fails if the VB6 runtime (which includes the Err object among other thigs) is not initialized on the running thread.

    Using typelib APIs does *not* set Err.LastDllError after calling the entry point, *unless* specifically instructed w/ the usesgetlasterror attribute in the IDL declaration.
    I got the problem solved by using RemoveLastDllError module function at the beginning in Form_Load by directly using the API without having to use type lib from "Multithreading in VB6 part 1" of Trick's code bank.

    I thank both Trick for the example and Wqewto for the explanation.

    regards,
    JSvenu

  21. #21
    PowerPoster
    Join Date
    Feb 2015
    Posts
    2,797

    Re: using VbTrickThreading-master examples without the typelibs for Callback and Mar

    As i promised i made the example of using modTrickUnregCOM and modMultiThreading2 modules. It creates each external object in its own thread and you can access to it from main thread. Notice, you should compile the example to see threading. It works in main thread in IDE.
    Code:
    Option Explicit
    
    ' // Each plugin is created in its own thread.
    ' // You should compile the example to see result.
    ' // It creates the plugins in main thread in IDE.
    
    Dim m_cPlugins  As Collection   ' // List of CPluginItem marshaled instances
    Dim m_cAsyncIDs As Collection   ' // List of appropriate async ids (used to wait for thread completion)
    
    ' // Scan folder
    Private Sub ScanPlugins()
        Dim cFso        As FileSystemObject
        Dim cFolder     As Folder
        Dim cFile       As File
        Dim bIsInIDE    As Boolean
        
        Set cFso = New FileSystemObject
        
        lstPlugins.Clear
        Set m_cPlugins = New Collection
        Set m_cAsyncIDs = New Collection
        
        Debug.Assert MakeTrue(bIsInIDE)
        
        ' // In IDE we use other folder
        If bIsInIDE Then
            Set cFolder = cFso.GetFolder(App.Path & "\Binaries")
        Else
            Set cFolder = cFso.GetFolder(App.Path)
        End If
        
        For Each cFile In cFolder.Files
            ' // Try to load file
            LoadPlugin cFile.Path
        Next
        
        cmdShowThreadID.Enabled = m_cPlugins.count > 0
        
    End Sub
    
    Private Sub LoadPlugin( _
                ByRef sPath As String)
        Dim cItem       As Object
        Dim lAID        As Long
        Dim tClsIds()   As GUID
        Dim sNames()    As String
        Dim lCount      As Long
        
        On Error GoTo error_handler
        
        ' // Get list of all co-clasees (plugins in dll)
        If Not GetAllCoclasses(sPath, tClsIds(), sNames(), lCount) Then Exit Sub
    
        Do While lCount > 0
            
            ' // Create CPluginItem in new thread
            Set cItem = CreatePrivateObjectByNameInNewThread("CPluginItem", , lAID)
            If cItem Is Nothing Then Exit Sub
            
            ' // This method is called from current (main) to different thread
            If Not cItem.Initialize(sPath, sNames(lCount - 1)) Then GoTo continue
            
            m_cAsyncIDs.Add lAID
            m_cPlugins.Add cItem
            lstPlugins.AddItem cItem.GetInfo()  ' // Call between threads
            
    continue:
            
            lCount = lCount - 1
            
        Loop
    
    error_handler:
        
    End Sub
    
    Private Sub cmdShowThreadID_Click()
        ' // Call the method of plugin which is in other thread
        ' // You can use asynch call if need. The messagebox is
        ' // appeared in other thread and it isn't modal related
        ' // to current thread
        m_cPlugins(lstPlugins.ListIndex + 1).ShowThreadID
    End Sub
    
    Private Sub Form_Load()
        modMultiThreading.Initialize
        modMultiThreading.EnablePrivateMarshaling True
        ScanPlugins
    End Sub
    
    Private Sub Form_Unload(Cancel As Integer)
        Dim vItem   As Variant
        
        ' // This runs the threads completions
        Set m_cPlugins = Nothing
        
        ' // Wait until all the threads are finised
        For Each vItem In m_cAsyncIDs
            modMultiThreading.WaitForObjectThreadCompletion vItem
        Next
        
        modMultiThreading.Uninitialize
        
    End Sub
    
    Private Function MakeTrue( _
                     ByRef bValue As Boolean) As Boolean
        MakeTrue = True
        bValue = True
    End Function
    Code:
    Option Explicit
    
    Private m_cPlugin   As IPluginInfo
    Private m_sPath     As String
    
    Public Property Get Path() As String
        Path = m_sPath
    End Property
    
    ' // IDispatch layer. You can use IPluginInfo::ShowThreadID directly
    ' // but it requires user interface marshaling. You can see examples
    ' // of that in VbTrickThreading demos.
    Public Sub ShowThreadID()
        If Not m_cPlugin Is Nothing Then
            m_cPlugin.ShowThreadID
        End If
    End Sub
    
    ' // The same
    Public Property Get GetInfo() As String
        If Not m_cPlugin Is Nothing Then
            GetInfo = m_cPlugin.GetPluginInfo
        End If
    End Property
    
    ' // Initialize the plugin
    ' // This method is called from main thread using proxy-stub layer
    Public Function Initialize( _
                    ByRef sPath As String, _
                    ByRef sName As String) As Boolean
                        
        Set m_cPlugin = modUnregCOM.CreateObjectEx2(sPath, sPath, sName)
         
        Initialize = Not m_cPlugin Is Nothing
        
        If Initialize Then
            m_sPath = sPath
        Else
            m_sPath = vbNullString
        End If
        
    End Function
    
    Public Sub Uninitialize()
    
        If Len(m_sPath) Then
            
            Set m_cPlugin = Nothing
            
            UnloadLibrary m_sPath
            
            m_sPath = vbNullString
            
        End If
        
    End Sub
    
    Private Sub Class_Terminate()
        Uninitialize
    End Sub
    Attached Files Attached Files

  22. #22
    Fanatic Member
    Join Date
    Jun 2016
    Location
    España
    Posts
    630

    Re: using VbTrickThreading-master examples without the typelibs for Callback and Mar

    Thank you very much, Trick.
    The first tests performed work perfectly.
    I don't understand much about Marshaling and TLB,
    although assigning it as an object I can make direct calls to the object.
    So it works perfect as I wanted, I will study Marshaling and TLB better.


    Thanks a lot.

  23. #23
    Fanatic Member
    Join Date
    Jun 2016
    Location
    España
    Posts
    630

    Re: using VbTrickThreading-master examples without the typelibs for Callback and Mar

    sorry
    Last edited by yokesee; Jan 20th, 2020 at 10:07 AM.

  24. #24

  25. #25

    Thread Starter
    Hyperactive Member
    Join Date
    Apr 2015
    Posts
    356

    Re: using VbTrickThreading-master examples without the typelibs for Callback and Mar

    Dear Trick,

    You were using .res file and .xml file in TrickMTDownloader and MarshalUserInterface applications in vb6.
    Can you tell me why we use here and what is the purpose of using them as I am unable to run both the applications.

    TrickMTDownloader
    When I build and run Downloader.exe I get the following error in message box

    The application has failed to start because its side-by-side configuration is incorrect. Please see the application event log or use the command-line sxstrace.exe tool for more detail.

    MarshalUserInterface
    When I built MarshalUserInterface and run the compiled exe it is crashing.

    Please clarify.

    regards,
    JSVenu

  26. #26

    Thread Starter
    Hyperactive Member
    Join Date
    Apr 2015
    Posts
    356

    Re: using VbTrickThreading-master examples without the typelibs for Callback and Mar

    Dear FunkyDexter,Wqewto,Eduardo,



    I can tell you that I do not know the questions I have been asking are suspicious in nature and associated with the sort of techniques typically used to produce malware since I was asking only to understand and improve my understanding in VB6.In all the queries you can see that I am asking questions which are related to learn multithreading and COM in easy way thru vb6 similar to win32 c/c++ programming.
    In win32 programming I can use free threading in non-COM.But I was having little knowledge about COM even in C/C++ which I understood somewhat better thru vb6.In vb6 use of Type libraries was new to me and we have to seperately write it so I asked can there be any other way to use apis directly without typelib.In MSDN I have seen ADO uses free threading and it can be used in vb6.The I thought that there can be easy way to do free threading in vb6 also and asked question in vb6 from which I could understand COM better.

    This is the whole explanation I can sincerely give you and I am very sorry for making you think that my behaviour is suspicious.


    regards,
    JSVenu

  27. #27
    Super Moderator FunkyDexter's Avatar
    Join Date
    Apr 2005
    Location
    An obscure body in the SK system. The inhabitants call it Earth
    Posts
    7,957

    Re: using VbTrickThreading-master examples without the typelibs for Callback and Mar

    The problem is that you're asking questions about how to make VB do things which VB is generally unsuited to doing. VB (or more accurately the Com programming model) provides mechanisms to achieve comparable end goals which are considered "safe" and do not require you to pursue the techniques you're pursuing. That begs the question "why would you pursue these techniques instead of using those provided by VB and it's framework?"

    There are legitimate answers to that question. As coders we sometimes need to step outside the safe constraints a framework places upon us to achieve some specific goal. However, we recognise that people generally shouldn't be doing so without good reason. That's why, when we see someone heading down those paths, we legitimately ask them why. If they fail to provide a good answer that acts as a red flag that they're likely to be trying to do something they shouldn't.

    So far the only answer you've given us is that you want to know those techniques but that was already obvious from the fact that you asked the question and it really doesn't speak to your ultimate motives. Essentially, all you've said is "teach me to be a better hacker... because I want to be a better hacker". That position is going to get short shrift around here.


    Edit> By the way, your use of bolding comes across as shouting and may turn people off. I don't think that's how you mean it to come across but it's something you might want to consider.
    Last edited by FunkyDexter; Jan 23rd, 2020 at 06:57 AM.
    The best argument against democracy is a five minute conversation with the average voter - Winston Churchill

    Hadoop actually sounds more like the way they greet each other in Yorkshire - Inferrd

  28. #28
    PowerPoster
    Join Date
    Jan 2020
    Posts
    5,538

    Re: using VbTrickThreading-master examples without the typelibs for Callback and Mar

    i write more words,use more hours,while delete my reply?
    maybe my answer is not like this subject?
    but i think my Createthread method is easy.
    maybe i don't know VbTrickThreading,It's really useful in some ways

  29. #29
    PowerPoster
    Join Date
    Jan 2020
    Posts
    5,538

    Re: using VbTrickThreading-master examples without the typelibs for Callback and Mar

    it's my thread bbs page,maybe my method is more easy.
    your question will Find a solution
    =========

    the best VB6 CreateThread(support ocx,Support UserControl)-VBForums
    http://www.vbforums.com/showthread.p...t-UserControl)
    Last edited by xiaoyao; Jan 23rd, 2020 at 12:47 PM.

  30. #30
    PowerPoster
    Join Date
    Feb 2015
    Posts
    2,797

    Re: using VbTrickThreading-master examples without the typelibs for Callback and Mar

    maybe i don't know VbTrickThreading
    It contains VBCreateThread function the analog of CreateThread API. The Julia fractal demo contains the usage of that function:
    Code:
    ' // Generate Julia Set to glPixels() array
    ' // lThreadCount - number of threads to draw
    ' // The function divides whole canvas into areas and creates threads which draw these areas
    Public Sub GenerateJulia( _
               ByVal cPic As PictureBox, _
               ByVal lThreadCount As Long)
     
        .  .  .
        
        For lIndex = 0 To lThreadCount - 1
            
            .  .  .
            
            ' // Create thread
            gHandles(lIndex) = vbCreateThread(0, 0, AddressOf ThreadProc, VarPtr(mtThreadsData(lIndex)), 0, 0)
        
        Next
    
    End Sub
    
    ' // This function calculates the part of Julia Set
    Private Function ThreadProc( _
                     ByRef tData As tThreadData) As Long
        
        .  .  .
        
        For lY = 0 To tData.lHeight - 1
            
            .  .  .
            
            For lX = 0 To tData.lWidth - 1
                
                glPixels(lX + tData.lX, lY + tData.lY) = glPalette(Julia(fX, fY))
                fX = fX + fStepX
                
            Next
            
            fX = tData.lX / tData.lTotalWidth * 2 - 1
            fY = fY + fStepY
            
        Next
        
    End Function
    The function ThreadProc is called from the different threads to draw the Julia set simultaneously.

  31. #31
    PowerPoster
    Join Date
    Jan 2020
    Posts
    5,538

    Re: using VbTrickThreading-master examples without the typelibs for Callback and Mar

    Code:
    Private Sub Command3_Click()
    CreateNewThread AddressOf ThreadTest, 33&, 0&
    
    End Sub
    
    Public Sub ThreadTest(ByVal lpParam As Long)
        InitFun
        msgbox "put your code here in a *.bas file"
        ExitFun
    End Sub

  32. #32

    Thread Starter
    Hyperactive Member
    Join Date
    Apr 2015
    Posts
    356

    Re: using VbTrickThreading-master examples without the typelibs for Callback and Mar

    Quote Originally Posted by FunkyDexter View Post
    The problem is that you're asking questions about how to make VB do things which VB is generally unsuited to doing. VB (or more accurately the Com programming model) provides mechanisms to achieve comparable end goals which are considered "safe" and do not require you to pursue the techniques you're pursuing. That begs the question "why would you pursue these techniques instead of using those provided by VB and it's framework?"

    There are legitimate answers to that question. As coders we sometimes need to step outside the safe constraints a framework places upon us to achieve some specific goal. However, we recognise that people generally shouldn't be doing so without good reason. That's why, when we see someone heading down those paths, we legitimately ask them why. If they fail to provide a good answer that acts as a red flag that they're likely to be trying to do something they shouldn't.

    So far the only answer you've given us is that you want to know those techniques but that was already obvious from the fact that you asked the question and it really doesn't speak to your ultimate motives. Essentially, all you've said is "teach me to be a better hacker... because I want to be a better hacker". That position is going to get short shrift around here.


    Edit> By the way, your use of bolding comes across as shouting and may turn people off. I don't think that's how you mean it to come across but it's something you might want to consider.
    Dear FunkyDexter,

    Thankyou for the awesome clarification.
    I understood what you mean and I can say that I will try to sincerely learn and use vb6 including advanced tecchniques of c/c++ in vb6 in a safe way to use them in good way rather than becoming hacker since I really love VB6.

    regards,
    JSVenu
    Last edited by jsvenu; Jan 23rd, 2020 at 10:33 PM.

  33. #33

    Thread Starter
    Hyperactive Member
    Join Date
    Apr 2015
    Posts
    356

    Re: using VbTrickThreading-master examples without the typelibs for Callback and Mar

    Quote Originally Posted by xiaoyao View Post
    Code:
    Private Sub Command3_Click()
    CreateNewThread AddressOf ThreadTest, 33&, 0&
    
    End Sub
    
    Public Sub ThreadTest(ByVal lpParam As Long)
        InitFun
        msgbox "put your code here in a *.bas file"
        ExitFun
    End Sub
    Dear xiaoyao,

    Thankyou for the reply.

    Your thread and Trick's thread use same api code for initializing runtime in new thread as follows:

    CreateIExprSrvObj
    CoInitialize
    VBDllGetClassObject (...)

    Your InitFun module function does the above initialisation.
    Upto here both are same.

    But the question here is initializing project context of activex control(or activex dll) which is user control from another activex control project and not activex control(user control) in the same project in which the activex control is used.

    Here you were using activex control(or activex dll) in the same exe project and no project context initialization is required as it is the same exe project whose context is initialized by default.

    When you are working with two different projects in which one is the main exe project and the other is the activex dll or activex ocx which is loaded to the main exe,
    the project context of the dll or ocx project has to be initialized in main exe project.

    If you don't initialize runtime you can use any APIs declared only in typelib (Using typelib APIs does *not* set Err.LastDllError after calling the entry point, *unless* specifically instructed w/ the
    usesgetlasterror attribute in the IDL declaration.) as already explained by Wqewto in post #2.
    Still if you want to use API directly without runtime init instead of typelib use the following RemoveLastDllError module function at the startup code in activex ocx or dll project from "Multithreading in VB6 part 1" of Trick's code bank which is as follows(which I already mentined in post #20):

    Code:
    Public Sub RemoveLastDllError()
        Dim hMod    As Long
        Dim lpProc  As Long
        hMod = GetModuleHandle(StrPtr("msvbvm60"))
        lpProc = GetProcAddress(hMod, "__vbaSetSystemError")
        VirtualProtect lpProc, 1, PAGE_EXECUTE_READWRITE, 0
        GetMem1 &HC3, ByVal lpProc
    End Sub
    
    regards,
    JSVenu
    Last edited by jsvenu; Jan 24th, 2020 at 04:29 AM.

  34. #34
    PowerPoster
    Join Date
    Jun 2013
    Posts
    7,454

    Re: using VbTrickThreading-master examples without the typelibs for Callback and Mar

    Quote Originally Posted by jsvenu View Post
    But the question here is initializing project context of activex control(or activex dll)
    which is user control from another activex control project ...
    Hmm, if it is all that this discussion about (managing Forms on their own Threads,
    loading Controls from external OCXes onto these threaded Forms) -
    then please take a look at this new CodeBank entry: http://www.vbforums.com/showthread.p...-(simple-Demo)

    Just a handful of normal VB6-Code is needed (no API-calls, and no ASM-hacks) for "threaded Forms, loading an OCX".

    Olaf

  35. #35

    Thread Starter
    Hyperactive Member
    Join Date
    Apr 2015
    Posts
    356

    Re: using VbTrickThreading-master examples without the typelibs for Callback and Mar

    Quote Originally Posted by Schmidt View Post
    Hmm, if it is all that this discussion about (managing Forms on their own Threads,
    loading Controls from external OCXes onto these threaded Forms) -
    then please take a look at this new CodeBank entry: http://www.vbforums.com/showthread.p...-(simple-Demo)

    Just a handful of normal VB6-Code is needed (no API-calls, and no ASM-hacks) for "threaded Forms, loading an OCX".

    Olaf
    Dear Schmidt,
    Thank you for the example.
    I have gone thru the activex exe example.

    Yes it is simple nice inproc activex application .


    regards,
    JSVenu
    Last edited by jsvenu; Jan 25th, 2020 at 03:31 AM. Reason: Corrected my observation as suggested by Schmidt

  36. #36
    PowerPoster
    Join Date
    Jun 2013
    Posts
    7,454

    Re: using VbTrickThreading-master examples without the typelibs for Callback and Mar

    Quote Originally Posted by jsvenu View Post
    I have gone thru the activex exe example.The main problem here is each form is loaded into STA in seperate exe.
    No, the threads (the STAs) are created InProcess ... there's only one Exe-Process ("AxThreading.exe") which is running,
    no matter how often you press the Button to create another threaded Form (which all show-up in the TaskBar of course).

    Quote Originally Posted by jsvenu View Post
    So when we click the button ten times ten exes are created
    as can be seen in task manager.
    That observation is wrong, please test properly...

    Olaf

  37. #37

  38. #38
    PowerPoster
    Join Date
    Jun 2013
    Posts
    7,454

    Re: using VbTrickThreading-master examples without the typelibs for Callback and Mar

    Quote Originally Posted by The trick View Post
    The AX-Exe approach isn't applicable in several cases.
    Well, for beginners (who want to learn, how VB6's STA-based threading works),
    it is certainly the place to "start from".

    Quote Originally Posted by The trick View Post
    For example it requires administrative rights to Run.
    Only on the very first run, one has to "run as Administrator" - or (to avoid that) -
    a decent Setup could be used, to pre-register the Ax-Exe (along with the external OCXes).

    It's also quite easy, to move (in a second step, after understanding Ax-Exe-based STA-handling),
    from the Ax-Exe-approach to a "Standard-Exe + Ax-Dll-based STA"-approach (to avoid these "registry issues" entirely).

    Quote Originally Posted by The trick View Post
    You can't use AX-EXE approach to accept callbacks from different threads.
    One can (by doing the usual thing, handling the incoming thread-call via a TypeLib-defined PostMessage-delegation).

    Besides, JSVenus threads are all about "showing Forms on new threads",
    and that's covered by my example quite nicely I think.

    He also stated, that he wants to learn about threading in VB6 (which is all about handling of ThreadObjects on STAs).
    Any attempts at "FreeThreading" or "VB6-Runtime-hacks via ASM" are inherently instable and not generically usable.

    Olaf

  39. #39
    PowerPoster
    Join Date
    Feb 2015
    Posts
    2,797

    Re: using VbTrickThreading-master examples without the typelibs for Callback and Mar

    Well, for beginners (who want to learn, how VB6's STA-based threading works),
    it is certainly the place to "start from".
    Yes, that's applicable for beginners and on some other cases. I just told about the cases when it isn't applicable . Understanding how does STA work (generally) like Message Pumping, Marshaling etc. is exactly hidden from a developer. I think it's quite bad regarding to learning "how does STA works". If one wants to migrate then to an other language that knowledge are useful.

    Only on the very first run, one has to "run as Administrator" - or (to avoid that) -
    a decent Setup could be used, to pre-register the Ax-Exe (along with the external OCXes).
    Yes, you're right. Seems (if i'm not wrong, i don't remember exactly) there is a way to run it without rights and registration.

    It's also quite easy, to move (in a second step, after understanding Ax-Exe-based STA-handling),
    from the Ax-Exe-approach to a "Standard-Exe + Ax-Dll-based STA"-approach (to avoid these "registry issues" entirely).
    Not-always. For example SxS is incompatible with some VB6-runtime things. Using my module/framework it's quite easy to work with threading at more low-level (and more control) manner (like in C, C++ for example) but you can use high-level function if you need.

    One can (by doing the usual thing, handling the incoming thread-call via a TypeLib-defined PostMessage-delegation).
    One can, but one may not know the restrictions/pitfails. For example if you receive call from a thread you can't use global/static variables because they are stored at TLS location offset. Using my module one can just receive callback using couple functions. If you tell about simple approach for beginners it's seems not suitable.

    He also stated, that he wants to learn about threading in VB6 (which is all about handling of ThreadObjects on STAs).
    Threading isn't "all about handling of ThreadObjects on STAs".

    Any attempts at "FreeThreading" or "VB6-Runtime-hacks via ASM" are inherently instable and not generically usable.
    JSVenus thread is for usage/internal structure VbTrickThreading/msvbvm module to achieve multithreading. If you hate it or it's unstable for you or you afraid ASM or something like that you can report about errors etc here/CodeBank/GitHub.

  40. #40

    Thread Starter
    Hyperactive Member
    Join Date
    Apr 2015
    Posts
    356

    Re: using VbTrickThreading-master examples without the typelibs for Callback and Mar

    Quote Originally Posted by Schmidt View Post
    Hmm, if it is all that this discussion about (managing Forms on their own Threads,
    loading Controls from external OCXes onto these threaded Forms) -
    then please take a look at this new CodeBank entry: http://www.vbforums.com/showthread.p...-(simple-Demo)

    Just a handful of normal VB6-Code is needed (no API-calls, and no ASM-hacks) for "threaded Forms, loading an OCX".

    Olaf
    Dear olaf,
    Yes you are right it is inproc example only.Sorry for understanding in a wrong way.

    Dear Trick,

    If we use any api call with declare in active control project like when we click on a added button in ocx project and open it in exe I think project context for the ocx is also initialized automatically in the new thread and still we have to use your RemoveLastDllError module function to avoid crash due to API usage.Please clarify am I correct.




    regards,
    JSVenu

Page 1 of 5 1234 ... 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