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