Is there a way to find a C ++ bad name for use in GetProcAddress?

A common “solution” for using GetProcAddress with C ++ is “extern" C, but this breaks the overload. Managing the name allows multiple functions to coexist if their signature is different. But is there a way to find these malformed names for GetProcAddress ?

+4
source share
3 answers

The VC ++ compiler knows its name-switching scheme, so why not use this? Inside template<typename T> T GetProcAddress(HMODULE h, const char* name) __FUNCDNAME__ macro contains the garbled name GetProcAddress . This includes part T So, inside GetProcAddress<void(*)(int) we have a substring with the distorted name void(*)(int) . From this we can trivially infer the distorted name void foo(int);

This code is based on the VC ++ __FUNCDNAME__ . For MinGW, you will need to base this on __PRETTY_FUNCTION__ instead .

 FARPROC GetProcAddress_CppImpl(HMODULE h, const char* name, std::string const& Signature) { // The signature of T appears twice in the signature of T GetProcAddress<T>(HMODULE, const char*) size_t len = Signature.find("@@YA"); std::string templateParam = Signature.substr(0, len); std::string returnType = Signature.substr(len+4); returnType.resize(templateParam.size()); // Strip off our own arguments (HMODULE and const char*) assert(templateParam == returnType); // templateParam and returnType are _pointers_ to functions (P6), so adjust to function type (Y) std::string funName = "?" + std::string(name) + "@@Y" + templateParam.substr(2); return ::GetProcAddress(h, funName.c_str()); } template <typename T> T GetProcAddress(HMODULE h, const char* name) { // Get our own signature. We use `const char* name` to keep it simple. std::string Signature = __FUNCDNAME__ + 18; // Ignore prefix " ??$GetProcAddress@ " return reinterpret_cast<T>(GetProcAddress_CppImpl(h, name, Signature)); } // Showing the result struct Dummy { }; __declspec(dllexport) void foo( const char* s) { std::cout << s; } __declspec(dllexport) void foo( int i, Dummy ) { std::cout << "Overloaded foo(), got " << i << std::endl; } __declspec(dllexport) void foo( std::string const& s ) { std::cout << "Overloaded foo(), got " << s << std::endl; } __declspec(dllexport) int foo( std::map<std::string, double> volatile& ) { std::cout << "Overloaded foo(), complex type\n"; return 42; } int main() { HMODULE h = GetModuleHandleW(0); foo("Hello, "); auto pFoo1 = GetProcAddress<void (*)( const char*)>(h, "foo"); // This templated version of GetProcAddress is typesafe: You can't pass // a float to pFoo1. That is a compile-time error. pFoo1(" world\n"); auto pFoo2 = GetProcAddress<void (*)( int, Dummy )>(h, "foo"); pFoo2(42, Dummy()); // Again, typesafe. auto pFoo3 = GetProcAddress<void (*)( std::string const& )>(h, "foo"); pFoo3("std::string overload\n"); auto pFoo4 = GetProcAddress<int (*)( std::map<std::string, double> volatile& )>(h, "foo"); // pFoo4 != NULL, this overload exists. auto pFoo5 = GetProcAddress<void (*)( float )>(h, "foo"); // pFoo5==NULL - no such overload. } 
+4
source

Use dumpbin /exports 'file.dll' to get the stolen / unshared name of all characters.

+1
source

Unable to do this using GetProcAddress . However, one way to do this is to list all the exported functions for this particular module and perform pattern matching to find all the malformed names.

In particular, refer to this answer here . The only change you will need to make is to pass the MappedAsImage parameter and the MappedAsImage return value for the Base parameter to TRUE to call the ImageDirectoryEntryToData function.

 void EnumerateExportedFunctions(HMODULE hModule, vector<string>& slListOfDllFunctions) { DWORD *dNameRVAs(0); _IMAGE_EXPORT_DIRECTORY *ImageExportDirectory; unsigned long cDirSize; _LOADED_IMAGE LoadedImage; string sName; slListOfDllFunctions.clear(); ImageExportDirectory = (_IMAGE_EXPORT_DIRECTORY*) ImageDirectoryEntryToData(hModule, TRUE, IMAGE_DIRECTORY_ENTRY_EXPORT, &cDirSize); if (ImageExportDirectory != NULL) { dNameRVAs = (DWORD *)ImageRvaToVa(LoadedImage.FileHeader, LoadedImage.MappedAddress, ImageExportDirectory->AddressOfNames, NULL); for(size_t i = 0; i < ImageExportDirectory->NumberOfNames; i++) { sName = (char *)ImageRvaToVa(LoadedImage.FileHeader, LoadedImage.MappedAddress, dNameRVAs[i], NULL); slListOfDllFunctions.push_back(sName); } } } 
0
source

All Articles