Hello firehacker,
Can you provide me a working c/c++ sample project for vb6 multithreading like you have shown CreateBasicThread() in vbstreets.ru.
Thanks
Printable View
Hello firehacker,
Can you provide me a working c/c++ sample project for vb6 multithreading like you have shown CreateBasicThread() in vbstreets.ru.
Thanks
Hello FireHacker,
This is reply to https://www.vbforums.com/showthread....n-string/page2 for #58
Thankyou for the awesome detailed advanced explanation.
I was asking for a simple vb6 multithreading working example in the sense it is
1. A simple dll code in c/c++ which I can compile and generate dll
2 Which can be used by any vb6 std exe application for creating a new thread.
For me it is enough with any particular version of vb6 msvbvm60.dll (need not cover all versions) so that I can understand Sub Main suppression ,vbaaptoffset,how to create and initialize a new thread properly for which I am thankful to you.
Thanks
You could try to use this solution for multithreading.
Do you have troubles to translate from VB6 to C++?
Hello The Trick,
I have gone through the link you provided.Everything is done by modMultiThreading.bas module.It is not so easy to translate the module into c/c++ since it is so advanced that you are using many undocumented apis in it.You know how much I struggled to get rtcMsgBox api work which could not have happened without your awesome support.
I could not even understand what JSVenu suggested me for avoiding additional vb actx dll in my first post regarding undocumented APIs.
So I request you to provide me a simple c/c++ dll like I requested FireHacker containing same functionality as modMultiThreading2.bas for which I will be happy.
Thanks
Hello The Trick,
I wrote a small win32 c/c++ dll which exports a function initvbruntime() based on your modMultiThreading module as follows:
In the above code I used GetMem4 and VBDllGetClassObject APIs of msvbvm60.dllCode:#include "stdafx.h"
#include <ole2.h>
#include "vbsim1.h"
typedef long (__stdcall *pVBDllGetClassObject) (HINSTANCE Unknown1,long Unknown2,PVOID Unknown3_vbheader,REFCLSID, REFIID, LPVOID*);//HINSTANCE h REFCLSID
typedef long (__stdcall *pGetMem4) (PVOID src,PVOID dst);//,REFCLSID, REFIID, LPVOID*);//HINSTANCE h REFCLSID
pVBDllGetClassObject pv1;
pGetMem4 pRtlMoveMemory;
HANDLE vbHandle;
HANDLE msvbvmvbHandle;
IDispatch *IDisp=NULL;
// Exported function.
__declspec(dllexport) int initvbruntime(void)
{
INT vbDLLPointer;
PVOID VBLIBPointerThunRTMain;
PVOID VBLIBPointerVDGCO;
HANDLE VBThread;
PVOID VBLIBPointerDGCO;
PVOID ptr;
CLSID clsid;
HRESULT hr,hr1;
ULONG lOldProtect;
msvbvmvbHandle=LoadLibrary("msvbvm60.dll");
pRtlMoveMemory=(pGetMem4)GetProcAddress((struct HINSTANCE__ *)msvbvmvbHandle, "GetMem4");
vbHandle = GetModuleHandle(NULL);//LoadLibrary(DLLName);
//VBLIBPointerDGCO = GetProcAddress(vbHandle,"DllGetClassObject");
/* Load the VB DLL */
//vbDLLPointer = *(int*)((int)VBLIBPointerDGCO + 2); /* Get the Project Pointer */
// Get e_lfanew
pRtlMoveMemory((int*)((int)vbHandle + 0x3C),ptr);
//GetMem4 ByVal hModule + &H3C, ptr
// Get AddressOfEntryPoint
pRtlMoveMemory(*(int*)((int)ptr) + 0x28 + vbHandle,ptr);//compilation error C2036: 'void *' : unknown size
//GetMem4 ByVal ptr + &H28 + hModule, ptr
// Get VBHeader
pRtlMoveMemory(ptr + vbHandle + 1,VBLIBPointerDGCO);//compilation error C2110: cannot add two pointers
// Allow to write to that page
VirtualProtect(VBLIBPointerDGCO, 0x64, PAGE_EXECUTE_READWRITE, &lOldProtect);
// 'Remove Sub Main
//ptr = mpVbHeader + &H2C
//GetMem4 0&, ByVal ptr ' 'AddressOf mymain
pRtlMoveMemory(VBLIBPointerDGCO + 0x2C,0);//compilation error C2036: 'void *' : unknown size
VirtualProtect(VBLIBPointerDGCO, 0x64, lOldProtect, 0);
//GetMem4 ByVal ptr + hModule + 1, GetVBHeader
//msvbvmvbHandle=LoadLibrary("msvbvm60.dll");
VBLIBPointerThunRTMain = GetProcAddress((struct HINSTANCE__ *)msvbvmvbHandle,"ThunRTMain"); /* Get the VB Runtime Initialization Pointer */
pv1=(pVBDllGetClassObject)GetProcAddress((struct HINSTANCE__ *)msvbvmvbHandle, "VBDllGetClassObject");
try
{
hr1= pv1((struct HINSTANCE__ *)vbHandle,0, VBLIBPointerDGCO,clsid, IID_IDispatch, (LPVOID *)&IDisp);
catch(...)
{
if( FAILED( hr1 ) )
{
MessageBox(0,"\nVBDllGetClassObject failed",0,0);
}
}
return 42;
}
The code
1. finds the vbheader
2. removes sub main and
3. the vbheader is passed as input to VBDllGetClassObject() api for initializing vb runtime.
But I get following compilation errors when I try to build the dll which I mentioned in the above code:
Compiling...
vbsim1.cpp
E:\vbsim1\vbsim1.cpp(56) : error C2036: 'void *' : unknown size
E:\vbsim1\vbsim1.cpp(59) : error C2110: cannot add two pointers
E:\vbsim1\vbsim1.cpp(68) : error C2036: 'void *' : unknown size
Error executing cl.exe.
vbsim1.dll - 3 error(s), 0 warning(s)
Can you show how to use the GetMem4 and VBDllGetClassObject APIs of msvbvm60.dll properly without compilation errors
and use the dll to multithread in vb6.project link is attached.
Thanks
Dear smkperu,
You have to use specific type instead of PVOID for pointers when using GetMem4 or RtlMoveMemory.
All the errors are related to GetMem4 api call of msvbvm60.dll.
You also have to create a new copy of vbheader for initializing runtime in vb6 standard exe which is CreateVBheadercopy function in modmultithreading module of Trick's code.
regards,
JSVenu
Dear smkperu,
Replace your export function initruntime with the following code in the project and then your project builds without errors:
Code:// This is an example of an exported function.
VBSIM1_API int initvbruntime(void)
{
INT vbDLLPointer;
PVOID VBLIBPointerThunRTMain;
PVOID VBLIBPointerVDGCO;
HANDLE VBThread;
PVOID VBLIBPointerDGCO;
PVOID ptr;
CLSID clsid;
HRESULT hr,hr1;
ULONG lOldProtect;
msvbvmvbHandle=LoadLibrary("msvbvm60.dll");
pRtlMoveMemory=(pGetMem4)GetProcAddress((struct HINSTANCE__ *)msvbvmvbHandle, "GetMem4");
vbHandle = GetModuleHandle(NULL);//LoadLibrary(DLLName);
//VBLIBPointerDGCO = GetProcAddress(vbHandle,"DllGetClassObject");
/* Load the VB DLL */
//vbDLLPointer = *(int*)((int)VBLIBPointerDGCO + 2); /* Get the Project Pointer */
// Get e_lfanew
pRtlMoveMemory((int*)((int)vbHandle + 0x3C),ptr);
//GetMem4 ByVal hModule + &H3C, ptr
// Get AddressOfEntryPoint
// pRtlMoveMemory(*(int*)((int)ptr) + 0x28 + vbHandle,ptr);
ptr=(int*)((int*)ptr + 0x28 + (int)vbHandle);
//GetMem4 ByVal ptr + &H28 + hModule, ptr
// Get VBHeader
pRtlMoveMemory((int*)ptr + (int)vbHandle + 1,VBLIBPointerDGCO);
// Allow to write to that page
VirtualProtect(VBLIBPointerDGCO, 0x64, PAGE_EXECUTE_READWRITE, &lOldProtect);
// 'Remove Sub Main
//ptr = mpVbHeader + &H2C
//GetMem4 0&, ByVal ptr ' 'AddressOf mymain
pRtlMoveMemory((int*)((int)VBLIBPointerDGCO + 0x2C),0);
VirtualProtect(VBLIBPointerDGCO, 0x64, lOldProtect, 0);
//GetMem4 ByVal ptr + hModule + 1, GetVBHeader
//msvbvmvbHandle=LoadLibrary("msvbvm60.dll");
VBLIBPointerThunRTMain = GetProcAddress((struct HINSTANCE__ *)msvbvmvbHandle,"ThunRTMain"); /* Get the VB Runtime Initialization Pointer */
pv1=(pVBDllGetClassObject)GetProcAddress((struct HINSTANCE__ *)msvbvmvbHandle, "VBDllGetClassObject");
try
{
hr1= pv1((struct HINSTANCE__ *)vbHandle,0, VBLIBPointerDGCO,clsid, IID_IDispatch, (LPVOID *)&IDisp);//IID_IClassFactory, (LPVOID *)&pIFactory);
}
catch(...)
{
if( FAILED( hr1 ) )
{
MessageBox(0,"\nDllGetClassObject failed",0,0);
}
}
return 42;
}
regards,
JSVenu
You shouldn't use GetMem4 and another memory access functions because C/C++ already has pointers features. I don't know how to explain you all because you have the troubles with this elementary things. When you begin with threading you'll have much more troubles/deadlocks/etc.
And this is a very polite way of saying it :-))
When I first saw the code my WТF-per-minute metric sky-rocketed and I immediately jotted a reply with a lot of WТFs, LOLs and smilies but then just discarded it when my head cooled down.
Everyone has been there. . . Starting from multi-threading in a public forum can be a humiliating experience so patience (or silence) is a virtue here.
cheers,
</wqw>
:bigyello:
Actually, I disagree. The wizardry of making multi-threading work in VB6 is way and I mean way over my head. It looks like something God would write. It's just incomprehensible to me and other mere mortals. However, I have zero problems with nuances of writing multi-threaded applications like deadlocks and synchronization.
I think the real problem here is that people are out there in the world seeing what others are doing in other languages. I mean take Python. It's dead simple to write multi-threaded code in that language. Then you have languages like JavaScript make it easy to write asynchronous code. And of course .Net makes it very easy to write all kinds of multi-threaded and asynchronous code. Programmers are out there seeing these things and think they can just come to VB6 and do the same thing. VB6 is 20+ years old. You can't expect to do these things with the same ease. You're going to have to get your hands dirty by getting down into the plumbing.
A lot of people think I hate VB6 because of the things I say especially with regards to how it compares to .Net and other modern languages. No, it's not hate. Threads like this are the reason why. You're going to really struggle in VB6 if you're trying to do stuff like this without a low level understanding of COM, VB6, it's runtime along with other low levels stuff like pointers and memory allocation. Like you really have to know what you're doing.
Anyways, don't mind me. Just felt like ranting a little bit. Kinda tipsy right now. ;)
It just pains me so much to see developers way over their heads like this for no reason. Would it hurt so bad to give VB.Net a try where this would be easy as pie?
Hello The Trick,
Thankyou for the response.
Firehacker has explained about his c/c++ dll for vb6 multithreading which he gave awesome explanation.
So I tried that in c/c++ in a simple way for which you showed a link but in vb6.So I was trying to achieve atleast some part of it
in c/c++.Since I donot want to disturb you again and again I shall be happy if could provide me a simple c/c++ dll demo atleast with limited features
which exports a vbCreateThread function which can be used in vb6 std exe so that I can understand CreateIExprSrvObj,GetMem4(RtlMoveMemory),
CreateVBHeaderCopy and VBDllGetClassObject in order to improve my knowledge in vb6 as well as c/c++ for which I am indebted to you.
Thanks.
Niya, VB6 supports multithreading and had supported it since 1998 year. There are two types of project - ActiveX EXE and ActiveX DLL (OCX) where your code can live in the different ST-apartments. This is the quite famous information but most of the VB6-programmers i guess never read the official help. Most of the multithreading task can be solved within VB6 but peoples want to break rules and use unsafe things in VB6 shooting themself in the foot. I still don't understand why TS wants to use it and i won't help until i get answer because i think such tasks are related to malware coding. There is no issues if you breaks the rules when you know how things works and you can bypass some things to make the code more performanced or bypass some good restrictions. But when i see the code like above - i think this is no reason to help because there is no understanding at all and it will only get worse.
Ah well. Don't take what I wrote too seriously. I was a bit tipsy. Just kind of what I was thinking when reviewing this thread. I was just thinking out loud as it were.
Hello the Trick,
I donot know what to answer.
How can you judge me as trying to write malware or worse code.I tried to write in c/c++ the same code which you did in vb6 and
and you helped me by showing the link based on my conversation with FireHacker.Initially I did'nt even asked you for the help.
You only responded to me after which I tried and requested for help only for improvement and not anything else.
I donot bother about others who commented me since I only interacted with FireHacker ,yourself and JSVenu who really helped
me technically since my first post.
If you see the above code I am using GetModuleHandle(0) which takes instance handle of a vb6 std exe when this
dll is loaded into vb6 std exe which shows that I am considering using vb6 object instead of using msvbvm60.dll directly as you
suggested me in first post for initializing project.
Thanks
Because you can't explain why you need that. I suppose you want to create a malware because i know few scenarios where it's applicable, malware is one of them. Because of that most of AVs trigger on most of VB6 exacutable.Quote:
How can you judge me as trying to write malware or worse code.
I've already given you solution which works - https://www.vbforums.com/showthread....=1#post5548645
Hello The Trick,
Ok.From what you said I understand that If we try to initialize a project by creating a vb6 Ax object it is not a malware.Other than that all other methods is malware.
This is true for vb6 Ax dll as follows:
c/c++ standard exe in any thread:
//initialize project and runtime
coinitialize();
cocreateinstance();//create vb ax dll multiuse object
call any vb apis l;//works perfect
But for vb6 standard exe works by default only in main thread because the project and runtime
are already by default initialized.
In additional threads we cannot initialize runtime as above using
//initialize project and runtime
coinitialize
cocreateinstance();//create vb ax dll multiuse object
call any vb apis exported from the same above vb ax dll;//crashes in new threads in vb6 standard exe.
So for initializing project and runtime in standard exe you showed me a vb6 link from which I wanted
I wanted to develop a c/c++ dll with export function vbruntimeincdll() so that the above scenario works without crash as follows:
vb6 standard exe:
sub ThreadProc() 'vb6 non main thread
//initialize project and runtime for this new thread using c/c++ exported dll
vbruntimeincdll() 'c/c++ dll exported function
'initialize project and runtime
coinitialize()
cocreateinstance() 'create vb ax dll multiuse object
call any vb apis 'works fine in new threads in vb6 standard exe.
End ThreadProc
Since the above vbruntimeincdll() is a must for initializing runtime in new thread in vb6 standard exe I donot consider this as malware for which I asked a simple c/c++ dll with atleast limited features with the above vbruntimeincdll() exported function.
Thanks
The proper way is to transmit the call to specified apartment. VB6 oficially supports only ST apartments. If you want break the rule - use my module. There is no need to use an external C-DLL. Why won't you use module why do you need a C dll? Just use functions InitCurrentThreadAndCallFunction/InitCurrentThreadAndCallFunctionIDEProc. This is related to callbacks from arbitrary threads.
You still can initialize runtime and project from an AX-dll. I don't know why you decided it isn't possible.
Hello The Trick,
Even Initializing runtime and project from an AX-dll for a vb6 standard exe would not make
callbacks from arbitrary threads work fine without using functions InitCurrentThreadAndCallFunction/InitCurrentThreadAndCallFunctionIDEProc.
This is what I was trying to do using c/c++ dll which I already mentioned in https://www.vbforums.com/showthread....=1#post5552367.
Thanks
You still didn't describe, what it is you're developing (if it isn't malware).
Why is it that hard, to answer this simple question?
(you'd get a whole lot more replies, when the efforts "the regulars spend on your behalf",
will happen "for a good reason, in a scenario others can later identify - and learn from").
Give some context, man...
Olaf
Dear Trick,
From the discussions between you and SmkPeru I understand that
We have to use VB Ax dll for initializing runtime for non-malware solution.
There are two scenarios to achieve runtime initialization :
1. From non-vb standard exe ie c/c++ application from any thread as follows:
2.But in a vb6 standard exe the above does not work in new thread in the sense it will not execute code after CoCreateInstance and returns silently without error without crashing.Code:ThreadProc()
Set cObj = CreateIExprSrvObj(0, 4, 0)
CoInitialize ByVal 0&
pClsid = StrPtr("Vb AX DllSample.publicmultiuseclass")
tIID_IDispatch.c1 = 13.2096@
tIID_IDispatch.c2 = 504403158265495.5712@
'// create an instance and get IDispatch pointer
hr = CoCreateInstance(pClsid, 0, CLSCTX_INPROC_SERVER, VarPtr(tIID_IDispatch), cObj)
rtcMsgBox "in vbcallback"
End ThreadProc
But the following code works perfect and displays msgbox perfectly without crash or error:
SmkPeru wants to achieve the second scenario using vb Ax dll like scenario 1(non-malware solution) using c/c++ dll.Code:ThreadProc()
Set cObj = CreateIExprSrvObj(0, 4, 0)
CoInitialize ByVal 0&
pNewHeader = CreateVBHeaderCopy()
If pNewHeader Then
tIID.c2 = 504403158265495.5712@
VBDllGetClassObject hModule, 0, pNewHeader, tClsId, tIID, 0
End If
rtcMsgBox "in vbcallback"
End ThreadProc
regards,
JSVenu
I still don't understand. If you want to initialize an AxDll project from a C++ application you should use CoCreateInstance - nothing more. If you want to use callbacks in a StdExe project from a C++ application - use InitCurrentThreadAndCallFunction/InitCurrentThreadAndCallFunctionIDEProc - nothing more. Moreover there are the usage examples in the repository. Sometimes i guess jsvenu and smkperu are same person in the sense that they cannot explain normally what they need.
Yup - I've asked both of them multiple times now, what the "end-goal" of all this is,
but my simple question was always either outright ignored - or avoided with: "for learning purposes".
When I followed up with "if you learned what you needed, what will you build then?" -
also no answer was given.
To me that clearly hints to either "hacking- or cracking" (using the C-Dll for "hooking into VB6-runtime-based Apps").
The special requirements of the VB6-runtime-initialization (especially in threaded-scenarios),
are throwing off the existing "copy-paste"-tools for "aspiring h4ck0rs", I guess...
Olaf
Dear Trick,
I assume that the code in scenario 2 ie.,
cannot run without using VBDllGetClassObject and cannot be achieved using another vb ax dll like scenario 1 in vb6 standard exe in new thread.Code:ThreadProc()
Set cObj = CreateIExprSrvObj(0, 4, 0)
CoInitialize ByVal 0&
pNewHeader = CreateVBHeaderCopy()
If pNewHeader Then
tIID.c2 = 504403158265495.5712@
VBDllGetClassObject hModule, 0, pNewHeader, tClsId, tIID, 0
End If
rtcMsgBox "in vbcallback"
End ThreadProc
regards,
JSVenu
Hello The Trick,
If I want to use callbacks in a StdExe project from a C++ application - why should I use InitCurrentThreadAndCallFunction in vb6.Why not I shift the complexity from vb6 to c/c++ by implementing
InitCurrentThreadAndCallFunction in c/c++ and put vb6 std exe application as simple as possible.Why you are stopping me from doing it by discouraging Me and JSVenu.
In fact what JSVenu told is correct regarding scenario 2.
InitCurrentThreadAndCallFunction calls vbdllgetclassobject.
Thanks
JFYI, smkperu and JSVenu are the same person most probably. Moreover JSVenu has been (desperately) posting from multiple accounts in the past too.
cheers,
</wqw>
This thread is getting increasingly weird, and has a certain odor to it, which both Olaf and The Trick have stated pretty plainly. The inability to explain any legitimate use for the code when asked repeatedly certainly sounds like malware. The inability to keep straight which username is being posted under sounds more like Moti, though the question doesn't.
To the OP: If you feel this is legitimate, feel free to send a PM to any of the moderators explaining what the program is supposed to do.