tlhelp32 problem
André Johansen
andrejoh at c2i.net
Sat May 15 16:29:46 CDT 2004
Hi!
While trying to get Anarchy Online working with Wine, I discovered
that dynamically getting symbols from the running program does not
work properly in Wine.
The attached example code shows the problem; when running in Windows,
I get this output
The mangled name is "?Instantiate at MyTestClass@@SAPAV1 at PAVObjectArchive_c@fun@@@Z"
Searching in "ntdll.dll"
Searching in "kernel32.dll"
Searching in "Factory.dll"
Searching in "MSVCP60D.dll"
Searching in "MSVCRTD.dll"
Searching in "Test.dll"
Found the function at 00321023
Creating a new object!
The returned text is "Found the right one!"
whereas when running this in Wine, this is the output
[andrej at rivendell tst]$ PATH=$PATH:$PWD wine tst
The mangled name is "?Instantiate at MyTestClass@@SAPAV1 at PAVObjectArchive_c@fun@@@Z"
Searching in ""
Searching in ""
Searching in ""
Searching in ""
Searching in ""
Searching in ""
Searching in ""
Searching in ""
The returned text is "<function for "MyTestClass" not found>"
If the test for a ".dll" ending is removed (as can be seen in the
output, the name returned is empty, so it will always fail), this is
the output
[andrej at rivendell tst]$ PATH=$PATH:$PWD wine tst
The mangled name is "?Instantiate at MyTestClass@@SAPAV1 at PAVObjectArchive_c@fun@@@Z"
Searching in ""
Searching in ""
Found the function at 0x408a9023
Creating a new object!
The returned text is "Found the right one!"
-------------- next part --------------
#ifndef FACTORY_H
#define FACTORY_H
#ifdef FACTORY_EXPORTS
# define _FAC_DLL_EXPORTS _declspec( dllexport )
# else
# define _FAC_DLL_EXPORTS _declspec( dllimport )
# endif
#include <string>
namespace fun {
class _FAC_DLL_EXPORTS Serializable_c {
public:
virtual ~Serializable_c() {}
virtual std::string GetText() const = 0;
};
class _FAC_DLL_EXPORTS ObjectArchive_c {
public:
std::string GetClassText(const std::string& classname);
typedef Serializable_c* CreateFunction_t(ObjectArchive_c* archive);
CreateFunction_t* FindCreateFunction(const std::string& classname);
};
}
#endif // FACTORY
-------------- next part --------------
#include "factory.h"
#include <windows.h>
#include <assert.h>
#include <ctype.h>
#include <imagehlp.h>
#include <tlhelp32.h>
#include <typeinfo>
#include <mmsystem.h>
#include <string>
#include <iostream>
namespace fun {
std::string
ObjectArchive_c::GetClassText(const std::string& classname)
{
std::string text = "<function for \"" + classname + "\" not found>";
CreateFunction_t* func = FindCreateFunction(classname);
if ( func ) {
Serializable_c* obj = func(this);
text = obj->GetText();
}
return text;
}
ObjectArchive_c::CreateFunction_t*
ObjectArchive_c::FindCreateFunction( const std::string& cClassName )
{
std::string cSymName;
int nDepth = 0;
int nStart = 0;
int nNameSpaceID = -1;
// Create a mangled symbol name from the "outernamespace::innernamespace::classname" string
for ( unsigned int i = 0 ; i <= cClassName.size() ; ++i ) {
if ( i == cClassName.size() || cClassName[i] == ':' ) {
const char* pzName = cClassName.c_str() + nStart;
std::string cNamePart( pzName, i - nStart );
if ( nNameSpaceID == -1 && cNamePart == "fun" ) {
nNameSpaceID = nDepth;
}
cSymName = cNamePart + "@" + cSymName;
nStart = i +2;
nDepth++;
++i; // Skip the second colon
}
}
cSymName = "?Instantiate@" + cSymName + "@SAPAV";
for ( int i2 = 0 ; i2 < nDepth ; ++i2 ) {
cSymName += '1' + i2;
}
if ( nNameSpaceID == -1 ) {
cSymName += "@PAVObjectArchive_c at fun@@@Z";
} else {
cSymName += "@PAVObjectArchive_c@";
cSymName += '0' + nDepth - nNameSpaceID;
cSymName += "@@Z";
}
std::cout << "The mangled name is \"" << cSymName << "\"\n";
HANDLE hSnapshot = CreateToolhelp32Snapshot( TH32CS_SNAPMODULE, 0 );
MODULEENTRY32 sEntry;
sEntry.dwSize = sizeof(sEntry);
for ( BOOL bLoop = Module32First( hSnapshot, &sEntry ) ;
bLoop ; bLoop = Module32Next( hSnapshot, &sEntry ) ) {
std::cout << "Searching in \"" << sEntry.szModule << "\"\n";
int nStrLen = strlen(sEntry.szModule);
if( nStrLen > 4 && !_strnicmp(sEntry.szModule+nStrLen-4,".dll", 4) )
{
CreateFunction_t* pFnc =
(CreateFunction_t*) GetProcAddress( sEntry.hModule, cSymName.c_str() );
if ( pFnc != NULL ) {
std::cout << "Found the function at " << (void*)pFnc << std::endl;
CloseHandle( hSnapshot );
return pFnc;
}
}
}
CloseHandle( hSnapshot );
return 0;
}
}
-------------- next part --------------
// -*- mode: c++ -*-
#ifndef TEST_H
#define TEST_H
#include "../Factory/factory.h"
#ifdef TEST_EXPORTS
# define _TEST_DLL_EXPORTS _declspec( dllexport )
# else
# define _TEST_DLL_EXPORTS _declspec( dllimport )
# endif
class _TEST_DLL_EXPORTS MyTestClass : public fun::Serializable_c
{
public:
static void EnsureIncluded();
static MyTestClass* Instantiate(fun::ObjectArchive_c* archive);
virtual ~MyTestClass() {}
virtual std::string GetText() const;
};
#endif
-------------- next part --------------
#include "test.h"
#include <string>
#include <iostream>
void
MyTestClass::EnsureIncluded()
{
}
MyTestClass*
MyTestClass::Instantiate(fun::ObjectArchive_c* /*archive*/)
{
std::cout << "Creating a new object!\n";
return new MyTestClass;
}
std::string
MyTestClass::GetText() const
{
return std::string("Found the right one!");
}
-------------- next part --------------
#include "Test/test.h"
#include "Factory/factory.h"
#include <iostream>
#include <string>
int main() {
MyTestClass::EnsureIncluded();
fun::ObjectArchive_c a;
const std::string text = a.GetClassText("MyTestClass");
std::cout << "The returned text is \"" << text << "\"\n";
return 0;
}
-------------- next part --------------
(If anybody needs the compiled code, and/or MSDS project files, please
contact me directly.)
--
Try Anarchy Online http://www.anarchy-online.com/content/downloads/tryout/
Netiquette guidelines ftp://ftp.rfc-editor.org/in-notes/rfc1855.txt
How to quote properly http://www.i-hate-computers.demon.co.uk/
Hvordan sitere riktig http://home.online.no/~vidaandr/news/OBSquoting.html
More information about the wine-devel
mailing list