Re: how to call a vb6 standalone exe module function from c/c++ new thread-reg
make a stdcall standard dll function like :
Code:
function sum(a as long,b as long) as long
sum=a+b
'or dim XML AS XMLHTTP
end function
YOU NEED load msvbvm in function like this:
Code:
function sum(a as long,b as long) as long
'initialize STA and context in threadproc of new thread created using CreateThread API
CreateIExprSrvObj 0&, 4&, 0&
CoInitialize ByVal 0&
hModule = GetModuleHandle(0) //get module instance of vb6 standard exe in which the dll is loaded
' Get VBHeader as follows
' // Get e_lfanew
GetMem4 ByVal hModule + &H3C, ptr
' // Get AddressOfEntryPoint
GetMem4 ByVal ptr + &H28 + hModule, ptr
' // Get VBHeader
GetMem4 ByVal ptr + hModule + 1, pVBHeader
pNewHeader=CreateVBHeaderCopy
If pVBHeader Then
VBDllGetClassObject hModule , 0& , pNewHeader, aiid, tGuid, 0&
End If
sum=a+b
'or dim XML AS XMLHTTP
end function
Re: how to call a vb6 standalone exe module function from c/c++ new thread-reg
Originally Posted by xiaoyao
make a stdcall standard dll function like :
Code:
function sum(a as long,b as long) as long
sum=a+b
'or dim XML AS XMLHTTP
end function
YOU NEED load msvbvm in function like this:
Code:
function sum(a as long,b as long) as long
'initialize STA and context in threadproc of new thread created using CreateThread API
CreateIExprSrvObj 0&, 4&, 0&
CoInitialize ByVal 0&
hModule = GetModuleHandle(0) //get module instance of vb6 standard exe in which the dll is loaded
' Get VBHeader as follows
' // Get e_lfanew
GetMem4 ByVal hModule + &H3C, ptr
' // Get AddressOfEntryPoint
GetMem4 ByVal ptr + &H28 + hModule, ptr
' // Get VBHeader
GetMem4 ByVal ptr + hModule + 1, pVBHeader
pNewHeader=CreateVBHeaderCopy
If pVBHeader Then
VBDllGetClassObject hModule , 0& , pNewHeader, aiid, tGuid, 0&
End If
sum=a+b
'or dim XML AS XMLHTTP
end function
Hello Xiaoyao,
For the above code which is already there in vbcallback1 dll I want an equivalent code in c/c++ like
1. getting the vbheader structure of the vbstd exe thru its GetModuleHandle(0) and
2. then creating a copy of the same and calling
3. calling vbdllgetclassobject
The above 3 things are crucial for which I request Trick for c/c++ code.
when Initialize() exported function of vbcallback1 actx dll is called using fInititialize(0);
tls is allocated using tlsalloc() and at that index returned by tlsalloc() in the Threadproc(of modMultiThreading2.bas) the pData is stored using tlssetvalue() when we call InitCurrentThreadAndCallFunction exported function using fInitCurrentThreadAndCallFunction in ThreadProc of c/c++ code.
I can use tlsalloc,tlssetvalue and tlsgetvalue in c/c++ dll.But other tasks left are
1. How to get vbheader of vbstdexe in our c/c++ code.
2. Creating a copy of the obtained vbheader.
3. Calling vbdllgetclassobject using this header.
Can you provide code in c/c++ dll for the above 1,2 and 3 tasks so that I can implement exported Initialize,Uninitialize and InitCurrentThreadandCallFunction functions using c/c++.
Re: how to call a vb6 standalone exe module function from c/c++ new thread-reg
Hello Trick,
DllGetClassObject is used by c/c++ and VBDllGetClassObject is used by vb6 exe.
But when new thread of c/c++ std dll is used in vb6 std exe, c/c++ dll should use VBDllGetClassObject with copy of vbheader of stdexe as input because it is running in the context of vb6 std exe.
Can you show me a simple example of the same using c/c++.
Re: how to call a vb6 standalone exe module function from c/c++ new thread-reg
Hello Trick,
Finally I made getting vbheader and obtaining its copy and calling vbdllgetclassobject with this new vbheader copy in new thread for calling
callback of vb std exe with c/c++ std dll code as follows:
Code:
// cdll.cpp : Defines the entry point for the DLL application.
//
#include "stdafx.h"
#include <Windows.h>
#include <ole2.h>
#include <objbase.h>
#include <atlbase.h>
#include <stdio.h>
typedef long (__stdcall *pVBDllGetClassObject) (HINSTANCE Unknown1,long Unknown2,PVOID Unknown3_vbheader,REFCLSID, REFIID, LPVOID*);
pVBDllGetClassObject pv1;
HANDLE vbHandle;
HANDLE msvbvmvbHandle;
IDispatch *IDisp=NULL;
HINSTANCE hMod;
DWORD d;
//declare a function pointer to call a funciton
// that returns an int
int ( __stdcall *lpVBFunction ) (int,int);
long glpfnTest;
typedef long (WINAPI pCreateIExprSrvObj)(long p1_0, long p2_4, long p3_0);
long (WINAPI *fCreateIExprSrvObj)(long p1_0, long p2_4, long p3_0);
struct TThreadData {
LPVOID pfn;
LONG l1;
LONG l2;
};
TThreadData *pData;
long (WINAPI *pfn1)(long,long);
BOOL WINAPI DllMain(HINSTANCE, DWORD,LPVOID){
return TRUE;
}
/////////////////////////createvbheadercopy implementation///////////////////////////////////////////////
int * pVBHeader;
HANDLE hHeadersHeap;
int* CreateVBHeaderCopy(int *vbHeader)
{
int *pHeader;
int *pOldProjInfo;
int *pProjInfo;
int *pObjTable;
int *pOldObjTable;
int lDifference;
int lIndex;
int *pNames[4];
int lModulesCount;
int *pDescriptors;
int *pOldDesc;
int *pVarBlock;
int lSizeOfHeaders;
int *ptr;
// Get size of all headers
lSizeOfHeaders = 0x6A + 0x23C + 0x54 + 0xC + 4;
pOldProjInfo=(vbHeader + 0x30);
pOldObjTable= pOldProjInfo + 0x4;
pOldDesc = pOldObjTable + 0x30;
lModulesCount= 3;//*(pOldObjTable + 0x2A);//hardcoded by counting the module count in vbstrd exe (form1,form2,module1) since I unable to get this
hHeadersHeap = HeapCreate(0, 0, 65536);
lSizeOfHeaders = lSizeOfHeaders + 0x30 * lModulesCount;
// Allocate memory for header
pHeader = (int*)HeapAlloc(hHeadersHeap, HEAP_ZERO_MEMORY, lSizeOfHeaders);
pHeader = pHeader + 4;
lDifference = (pHeader - pVBHeader);
pHeader=pVBHeader+0x6A;
pNames[0]=(pVBHeader + 0x58+0x10);
for (lIndex = 0;lIndex<=3;lIndex++)
pNames[lIndex] = pNames[lIndex] - lDifference;
ptr=pHeader + 0x58;
ptr=pNames[0]+0x10;
// In order to keep global variables
// Change the VbPublicObjectDescriptor.lpPublicBytes, VbPublicObjectDescriptor.lpStaticBytes
pProjInfo = (pHeader + 0x6A);
pProjInfo=pOldProjInfo+0x23C;
// Update on VBHeader
pProjInfo= (pHeader + 0x30);
// Create copy of Object table
pObjTable = pProjInfo + 0x23C;
pObjTable= pOldObjTable+0x54;
// Update
pObjTable = pProjInfo + 0x4;
// Allocate descriptors
pDescriptors = pObjTable + 0x54;
pDescriptors= pOldDesc+ lModulesCount * 0x30;
// Update
pDescriptors=pObjTable + 0x30;
// Allocate variables block
pVarBlock = pDescriptors + lModulesCount * 0x30;
for (lIndex = 0; lIndex++;lIndex<=lModulesCount - 1)
{
// Zero number of public and local variables
pVarBlock=pDescriptors + lIndex * 0x30 + 0x8;
ptr=(pDescriptors + lIndex * 0x30 + 0xC);
}
return pHeader;
}
////////////////////////////////////////////////////////////////////////
ULONG WINAPI ThreadProc(TThreadData *pData) {
fCreateIExprSrvObj(0,4,0);// for enabling API calls in new thread
/////////////////////////////////////get vbheader ofvb6 std exe//////////////////////////////////////////
int *cvbHeader;
int ptr=0;
int lvbHeader;
char s[10];
ULONG lOldProtect;
msvbvmvbHandle=LoadLibrary("msvbvm60.dll");
vbHandle = GetModuleHandle(NULL);//app instance of vbstd exe
ptr=*(int*)((int)vbHandle + 0x3C);
sprintf(s,"vbHandle+3C %d",ptr);
ptr=*(int*)(ptr + 0x28 + (int)vbHandle);
sprintf(s,"vbHandle+28 %d",ptr);
lvbHeader=*(int*)(ptr + (int)vbHandle+1);
// ptr=*(int*)(ptr+1);
sprintf(s,"vbHeader vc %d",lvbHeader);
VirtualProtect(&lvbHeader, 0x64, PAGE_EXECUTE_READWRITE, &lOldProtect);
// Remove Sub Main
ptr = lvbHeader + 0x2C;
int *ptr2=&ptr;
ptr2=NULL;
VirtualProtect(&lvbHeader, 0x64, lOldProtect, 0);
///////////////////getcopy of vbheader//////////////////////////////
cvbHeader=CreateVBHeaderCopy(&lvbHeader);
///get VBDllGetClassObject pointer from msvbvm60.dll
pv1=(pVBDllGetClassObject)GetProcAddress((struct HINSTANCE__ *)msvbvmvbHandle, "VBDllGetClassObject");
try
{
pv1((struct HINSTANCE__ *)vbHandle,0, cvbHeader,clsid, IID_IDispatch, (LPVOID *)&IDisp);//IID_IClassFactory, (LPVOID *)&pIFactory);//run VBDllGetClassObject with new vbheader
}
catch(...)
{
}
pfn1=(long (WINAPI *)(long,long))pData->pfn;
(*pfn1)(pData->l1 , pData->l2);//crashes here when we try to call vbstdexe callback
GlobalFree(pData);
return 0;
}
extern "C" HRESULT WINAPI CreateThreadAndCallback(LPVOID pfn, LONG l1, LONG l2) {
HRESULT hr = S_OK;
pData = (TThreadData*)GlobalAlloc(GMEM_ZEROINIT, sizeof(TThreadData));
if (!pData)
return E_OUTOFMEMORY;
pData->pfn = pfn;
pData->l1 = l1;
pData->l2 = l2;
hMod = LoadLibrary ("msvbvm60.dll");
if (hMod != NULL)
fCreateIExprSrvObj = (long (WINAPI *)(long , long , long ))GetProcAddress (hMod, "CreateIExprSrvObj");
if (!CreateThread(0,0,(LPTHREAD_START_ROUTINE)ThreadProc, pData, 0,&d)) {
GlobalFree(pData);
hr = E_FAIL;
}
return hr;
}
I am able to get vbheader of vbstd exe and get copy of new vbheader in c/c++.
Now when I call callback function it crashes. Please correct me where I am doing wrong so that the code works fine.
Complete project source code which includes vbstd exe project and cbdll(c/c++ std dll code) attached in cb folder in cb.zip.
.def file has to be incuded in cbdll c/c++ std dll project to export CreateThreadAndCallback as follows:
cbdll.def
Code:
EXPORTS
CreateThreadAndCallback
Thanks
Last edited by smkperu; Mar 18th, 2022 at 05:31 AM.