-
1 Attachment(s)
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
-
Re: using VbTrickThreading-master examples without the typelibs for Callback and Mar
Quote:
Originally Posted by
jsvenu
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>
-
1 Attachment(s)
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;
}
-
Re: using VbTrickThreading-master examples without the typelibs for Callback and Mar
Quote:
Originally Posted by
The trick
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
-
Re: using VbTrickThreading-master examples without the typelibs for Callback and Mar
Quote:
Originally Posted by
wqweto
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
-
Re: using VbTrickThreading-master examples without the typelibs for Callback and Mar
I don't know what should i answer. I gave you example and wqweto explained why you can't avoid type libraries.
-
Re: using VbTrickThreading-master examples without the typelibs for Callback and Mar
Quote:
Originally Posted by
The trick
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
-
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
-
Re: using VbTrickThreading-master examples without the typelibs for Callback and Mar
yokesee,
If you want to create an object in new thread and control it you can use CreatePrivateObjectByNameInNewThread or CreateActiveXObjectInNewThread functions. See examples here. Usually it depends on the end goal.
-
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
-
Re: using VbTrickThreading-master examples without the typelibs for Callback and Mar
yokesee,
What's your end goal? What should the example do? Please describe and i'll provide the example.
-
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
-
Re: using VbTrickThreading-master examples without the typelibs for Callback and Mar
Quote:
Originally Posted by
The trick
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
-
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.
Quote:
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.
-
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>
-
Re: using VbTrickThreading-master examples without the typelibs for Callback and Mar
Quote:
Originally Posted by
The trick
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
Quote:
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
-
Re: using VbTrickThreading-master examples without the typelibs for Callback and Mar
Quote:
@The trick (mailbox quota exceeded)
I've cleaned the storage.
-
Re: using VbTrickThreading-master examples without the typelibs for Callback and Mar
Quote:
Originally Posted by
The trick
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
-
Re: using VbTrickThreading-master examples without the typelibs for Callback and Mar
Quote:
Originally Posted by
wqweto
@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
-
Re: using VbTrickThreading-master examples without the typelibs for Callback and Mar
Dear Trick and Wqewto,
Wqewto's quote:
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
-
1 Attachment(s)
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
-
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.
-
Re: using VbTrickThreading-master examples without the typelibs for Callback and Mar
-
Re: using VbTrickThreading-master examples without the typelibs for Callback and Mar
-
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
-
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
-
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.
-
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
-
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)
-
Re: using VbTrickThreading-master examples without the typelibs for Callback and Mar
Quote:
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.
-
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
-
Re: using VbTrickThreading-master examples without the typelibs for Callback and Mar
Quote:
Originally Posted by
FunkyDexter
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
-
Re: using VbTrickThreading-master examples without the typelibs for Callback and Mar
Quote:
Originally Posted by
xiaoyao
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
-
Re: using VbTrickThreading-master examples without the typelibs for Callback and Mar
Quote:
Originally Posted by
jsvenu
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
-
Re: using VbTrickThreading-master examples without the typelibs for Callback and Mar
Quote:
Originally Posted by
Schmidt
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
-
Re: using VbTrickThreading-master examples without the typelibs for Callback and Mar
Quote:
Originally Posted by
jsvenu
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
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
-
Re: using VbTrickThreading-master examples without the typelibs for Callback and Mar
The AX-Exe approach isn't applicable in several cases. For example it requires administrative rights to Run. You can't use AX-EXE approach to accept callbacks from different threads. And so on...
-
Re: using VbTrickThreading-master examples without the typelibs for Callback and Mar
Quote:
Originally Posted by
The trick
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
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
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
-
Re: using VbTrickThreading-master examples without the typelibs for Callback and Mar
Quote:
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.
Quote:
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.
Quote:
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.
Quote:
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.
Quote:
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".
Quote:
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.
-
Re: using VbTrickThreading-master examples without the typelibs for Callback and Mar
Quote:
Originally Posted by
Schmidt
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
-
Re: using VbTrickThreading-master examples without the typelibs for Callback and Mar
Dear Olaf,
I added a button to the ExternalControl activex control and added button1 control as follows:
Private Sub Command1_Click()
Dim hUser32 As Long
hUser32 = GetModuleHandle(StrPtr("user32"))
MsgBox "in button1"
End Sub
When I call from AxThreading exe and click on button1 of activex control the declared api GetModuleHandle works
like a charm without crash even if we don't use RemoveLastDllError module function.Very nice example.Thank you olaf,
regards,
JSVenu
-
Re: using VbTrickThreading-master examples without the typelibs for Callback and Mar
Quote:
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.
When you create an object using DllGetClassObject (the standard ActiveX way) it always initializes the context for current thread.
-
Re: using VbTrickThreading-master examples without the typelibs for Callback and Mar
Quote:
Originally Posted by
The trick
When you create an object using DllGetClassObject (the standard ActiveX way) it always initializes the context for current thread.
Dear Trick,
Thankyou for the clear clarification.
regards,
JSVenu
-
Re: using VbTrickThreading-master examples without the typelibs for Callback and Mar
Quote:
Originally Posted by
jsvenu
I added a button to the ExternalControl activex control and added button1 control as follows:
Private Sub Command1_Click()
Dim hUser32 As Long
hUser32 = GetModuleHandle(StrPtr("user32"))
MsgBox "in button1"
End Sub
When I call from AxThreading exe and click on button1 of activex control the declared api GetModuleHandle works
like a charm without crash even if we don't use RemoveLastDllError module function.
Of course, because the example adheres to the "VB6-COM-STA threading-rules"
(implicitely, hidden from the User).
You can write basically the same thing (which adheres to these rules) also with the tricks Helper-module
(using AX-Dll-Classes instead of Ax-Exe-Classes) -
but then you'd have to learn, which of the provided "threading-helper-functionality" you'd have to avoid -
and which parts of it are "safe to use" (to not break those COM-threading-rules).
Olaf
-
1 Attachment(s)
Re: using VbTrickThreading-master examples without the typelibs for Callback and Mar
Quote:
When I call from AxThreading exe and click on button1 of activex control the declared api GetModuleHandle works
like a charm without crash even if we don't use RemoveLastDllError module function.
Code:
Private Sub cmdCreateThread_Click()
CloseHandle vbCreateThread(0, 0, AddressOf ThreadProc, 0, 0, 0)
End Sub
Private Sub Form_Load()
Me.Caption = App.ThreadID
Controls.Add("TestOCX.ctlTest", "Ctl1").Visible = True
End Sub
Code:
Option Explicit
Sub Main()
modMultiThreading.Initialize
frmMain.Show vbModal
modMultiThreading.Uninitialize
End Sub
Public Function ThreadProc( _
ByVal l As Long) As Long
Dim cFrm As frmMain
Set cFrm = New frmMain
cFrm.Show vbModal
End Function
Attachment 173945
The buttons creates a thread with form with external OCX. It requires no administrative right (for EXE), no install (for EXE), shared global variables, etc.
-
Re: using VbTrickThreading-master examples without the typelibs for Callback and Mar
Dear Trick and Olaf,
Thank you very much for the nice threading examples along with clear explanation.
regards,
JSVenu
-
Re: using VbTrickThreading-master examples without the typelibs for Callback and Mar
you do like on thread:Controls.Add("TestOCX.ctlTest", "Ctl1").Visible = True
when i add usercontrol on form by my hand,not use"controls.add"。
createthread for load the form with usercontrol or ocx,it,s error。
my english is not good,i can't understand your mean。maybe i need down your code for test.
,someone tell me,can use method(EbLoadRunTime
EbCreateContext
EbSetContextWorkerThread)
-
Re: using VbTrickThreading-master examples without the typelibs for Callback and Mar
xiaoyao, please attach the example.
-
Re: using VbTrickThreading-master examples without the typelibs for Callback and Mar
// 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)
your method need load ocx?by clsid?
I want createthread ( address of test) only in stand exe,no need ocx,no need stand dll,no need com dll,no need activex exe.
my method code lines so much,i want to find a easy way,can you help me?
Code:
sub test()
dim f as form2
set f=new form2 ' a usercontrol in this form.
f.show 1
end sub
-
Re: using VbTrickThreading-master examples without the typelibs for Callback and Mar
-
Re: using VbTrickThreading-master examples without the typelibs for Callback and Mar
Quote:
Originally Posted by
xiaoyao
I want createthread ( address of test) only in stand exe,
...no need ocx,no need stand dll,no need com dll,no need activex exe.
Why do you want to avoid using other (additional) libraries
(later shipping with your Exe, e.g. in a \Bin\-sub-folder)?
You are using VB6 after all - a high-level-language which has its strengths exactly there
(in glueing selfdescribing COM-Objects and COM-Controls together in a RADish way).
If it is because of "avoiding to make a proper installer" - then you should learn about regfree-COM mechanisms first.
VB6 was not made for "normal, free-threading"...
It supports a different kind of threading instead, which requires you to make use of ActiveX-Dlls
(or ActiveX-Exes), when you want to play things "by the (VB6)book" (to avoid instabilities).
Olaf
-
Re: using VbTrickThreading-master examples without the typelibs for Callback and Mar
where can i download project
i want test add usercontrol on thread form by toolbar ,not by ocx,how can i do?
Controls.Add("TestOCX.ctlTest",
-
Re: using VbTrickThreading-master examples without the typelibs for Callback and Mar
Quote:
Originally Posted by
xiaoyao
where can i download project
i want test add usercontrol on thread form by toolbar ,not by ocx,how can i do?
Controls.Add("TestOCX.ctlTest",
Dear xiaoyao,
Goto project ->components and browse for the .ocx file which you want to add to the project
and select open and then click ok.Automatically it will appear in tool bar which you can add to the form in the standard exe project.
regards,
JSVenu
-
Re: using VbTrickThreading-master examples without the typelibs for Callback and Mar
Code:
Private Sub cmdCreateThread_Click()
CloseHandle vbCreateThread(0, 0, AddressOf ThreadProc, 0, 0, 0)
End Sub
Private Sub Form_Load()
Me.Caption = App.ThreadID
Controls.Add("TestOCX.ctlTest", "Ctl1").Visible = True
End Sub
Code:
Option Explicit
Sub Main()
modMultiThreading.Initialize
frmMain.Show vbModal
modMultiThreading.Uninitialize
End Sub
Public Function ThreadProc( _
ByVal l As Long) As Long
Dim cFrm As frmMain
Set cFrm = New frmMain
cFrm.Show vbModal
End Function
where is the project link for download?
-
1 Attachment(s)
Re: using VbTrickThreading-master examples without the typelibs for Callback and Mar
Quote:
Originally Posted by
xiaoyao
Code:
Private Sub cmdCreateThread_Click()
CloseHandle vbCreateThread(0, 0, AddressOf ThreadProc, 0, 0, 0)
End Sub
Private Sub Form_Load()
Me.Caption = App.ThreadID
Controls.Add("TestOCX.ctlTest", "Ctl1").Visible = True
End Sub
Code:
Option Explicit
Sub Main()
modMultiThreading.Initialize
frmMain.Show vbModal
modMultiThreading.Uninitialize
End Sub
Public Function ThreadProc( _
ByVal l As Long) As Long
Dim cFrm As frmMain
Set cFrm = New frmMain
cFrm.Show vbModal
End Function
where is the project link for download?
Dear xiaoyao,
I am attaching the project.
You first build the ExternalControl.vbp activex project in the attachment folder and generate ExternalControl.ocx.
Then open the standard exe project(AxThreading.vbp) and add the ExternalControl.ocx thru project components to the tool bar and then add it to the form in the exe project and build it and run the compiled exe.Click on the button on the form.
regards,
JSVenu
-
1 Attachment(s)
Re: using VbTrickThreading-master examples without the typelibs for Callback and Mar
Quote:
// 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)
your method need load ocx?by clsid?
I want createthread ( address of test) only in stand exe,no need ocx,no need stand dll,no need com dll,no need activex exe.
my method code lines so much,i want to find a easy way,can you help me?
This is other project which i did for yokesee which shows the plugin-based concept with multithreading.
To create a thread you need to use this module. There are the examples of usage. You don't need any dependencies or dlls. This example just shows how to use an external OCX.
Quote:
where can i download project
I've attached the one. The modMultiThreading module you can get if you go to the link i provided above.
-
Re: using VbTrickThreading-master examples without the typelibs for Callback and Mar
Quote:
Originally Posted by
xiaoyao
you do like on thread:Controls.Add("TestOCX.ctlTest", "Ctl1").Visible = True
when i add usercontrol on form by my hand,not use"controls.add"。
createthread for load the form with usercontrol or ocx,it,s error。
my english is not good,i can't understand your mean。maybe i need down your code for test.
,someone tell me,can use method(EbLoadRunTime
EbCreateContext
EbSetContextWorkerThread)
Dear xiaoyao,
Here is the Link http://www.devx.com/vb2themax/CodeDownload/19804
for FreeThreader component for VB6 which uses above bold API in the same order for runtime initialisation in CreateMT and EnableEvents functions in assembly language in the file MULTITHREAD.Asm .
It is described as follows:
VB6 does not natively support free threading, but with this ActiveX library you can finally create multiple threads and make them communicate, write delegate functions (similarly to VB.NET) and use Structured Exception Handling. The full source code (in VB6 and Assembler) and some sample projects are provided.
This is also reply to http://www.vbforums.com/showthread.p...t-UserControl) post #9
Regarding internal working and stability of this code you can take help from Trick since I have less knowledge in ASM and already he helped me a lot regarding multithreading and he can better understand undocumented API like this.
regards,
JSVenu
-
1 Attachment(s)
Re: using VbTrickThreading-master examples without the typelibs for Callback and Mar
stand exe-thread ,can't support (usercontrols),how to fix it?
it's my thread bbs page:(code is to hard ,and lines to long,use asm,hook)
http://www.vbforums.com/showthread.p...t-UserControl)
download :http://www.vbforums.com/attachment.p...3&d=1579799200
-
Re: using VbTrickThreading-master examples without the typelibs for Callback and Mar
Quote:
Originally Posted by
The trick
This is other project which i did for yokesee which shows the plugin-based concept with multithreading.
To create a thread you need to use
this module. There are the examples of usage. You don't need any dependencies or dlls. This example just shows how to use an external OCX.
I've attached the one. The modMultiThreading module you can get if you go to the link i provided above.
==============
how to add usercontrols on forms object in thread?
(your project can add ocx,but can't support vb6 usercontrol)
Code:
Private obj As Object
Private Sub Command1_Click()
On Error GoTo ERR
Set obj = Me.Controls.Add("Project1.UserControl1", "UserControl1B")
obj.Visible = True
MsgBox obj.Width
Exit Sub
ERR:
MsgBox "ERR:" & ERR.Number & "," & ERR.Description
End Sub
sub test2
Dim ctlName As Control
Set ctlName = Form1.Controls.Add("Project1.UserControl1", "Text1", Form1)
ctlName.Visible = True
end sub
-
Re: using VbTrickThreading-master examples without the typelibs for Callback and Mar
Quote:
how to add usercontrols on forms object in thread?
(your project can add ocx,but can't support vb6 usercontrol)
Seems it's the problem with the runtime. It registers the "Global Factory" thru CoRegisterClassObject from the main STA and when you create an usercontrol it calls CoGetClassObject. CoGetClassObject checks the registered Apartment ID i.e. you can't get this "Global Factory" from the different apartment. The same problem you'll see with ActiveX EXE project type. To avoid this you can for example use Load statement with a control array. Additionally you can set the Threading Model to Apartment (1) in VBHeader.dwThreadFlags when you create a VBHeader. In this case each thread (namely STA) will have its own HXMod internal object like in ActiveX DLL. Only in this case you need to performs additional cleaning like VBCanUnloadNow, etc.