wxString wxAboutDialogInfo::GetDescriptionAndCredits() const { wxString s = GetDescription(); if ( !s.empty() ) s << wxT('\n'); if ( HasDevelopers() ) s << wxT('\n') << _("Developed by ") << AllAsString(GetDevelopers()); if ( HasDocWriters() ) s << wxT('\n') << _("Documentation by ") << AllAsString(GetDocWriters()); if ( HasArtists() ) s << wxT('\n') << _("Graphics art by ") << AllAsString(GetArtists()); if ( HasTranslators() ) s << wxT('\n') << _("Translations by ") << AllAsString(GetTranslators()); return s; }
/* * Patches an ASI Import Table for proper path translation */ void CThePlugin::ModuleInfo::PatchImports() { // Converts a rva pointer to a actual pointer in the process space from this ASI auto rva_to_ptr = [this](long rva) { return auto_ptr_cast((void*)((char*)(this->module) + rva)); }; // Used to find translators lowerbound at a sorted list of translators by library name auto fn_compare_translator_with_lib_lb = [](path_translator_base* a, const char* b) { return strcmp(a->GetLibName(), b, false) < 0; }; // Used to find translators upperbound at a sorted list of translators by library name auto fn_compare_translator_with_lib_ub = [](const char* a, path_translator_base* b) { return strcmp(a, b->GetLibName(), false) < 0; }; // Used to find translators lowerbound by symbol name auto fn_compare_translator_with_symbol = [](path_translator_base* a, const char* b) { return strcmp(a->GetSymbol(), b) < 0; }; // Get list of singletoned translators auto& list = GetTranslators(); // Setup pointers to headers in PE module IMAGE_THUNK_DATA32 *fname, *faddr; IMAGE_DOS_HEADER* dos = rva_to_ptr(0); IMAGE_NT_HEADERS* nt = rva_to_ptr(dos->e_lfanew); IMAGE_FILE_HEADER* pe = &nt->FileHeader; IMAGE_OPTIONAL_HEADER* opt = &nt->OptionalHeader; IMAGE_DATA_DIRECTORY* data = &opt->DataDirectory[0]; // Get address to import table if(data[IMAGE_DIRECTORY_ENTRY_IMPORT].Size == 0) return; IMAGE_IMPORT_DESCRIPTOR* imp = rva_to_ptr(data[IMAGE_DIRECTORY_ENTRY_IMPORT].VirtualAddress); // Iterate on each imported library... for(auto* lib = imp; lib->Name != 0; ++lib) { // Get library name... const char* libname = rva_to_ptr(lib->Name); // Check out if we have any translator for this library... auto it_lib = std::lower_bound(list.begin(), list.end(), libname, fn_compare_translator_with_lib_lb); if((it_lib != list.end() && !strcmp((*it_lib)->GetLibName(), libname, false)) == false) { // ...we don't, get 'almost any library' lower bound it_lib = std::lower_bound(list.begin(), list.end(), "", fn_compare_translator_with_lib_lb); } // If we have a lower bound to start searching symbols from, get into symbols searching! if(it_lib != list.end()) { // Find upper bound for this library auto it_lib_end = std::upper_bound(it_lib, list.end(), (*it_lib)->GetLibName(), fn_compare_translator_with_lib_ub); // Get pointer to thunks aka function names and function address tables fname = rva_to_ptr(lib->OriginalFirstThunk); faddr = rva_to_ptr(lib->FirstThunk); // Iterate on each name to see if we should patch it for(; fname->u1.Function; ++fname, ++faddr) { // Is this just a ordinal import? Skip it, we don't have a symbol name! if(fname->u1.Ordinal & IMAGE_ORDINAL_FLAG) continue; // Get the symbol name const char* symbolName = (char*)(((IMAGE_IMPORT_BY_NAME*)(rva_to_ptr(fname->u1.AddressOfData)))->Name); // Find arg translator from symbol... auto it_sym = std::lower_bound(it_lib, it_lib_end, symbolName, fn_compare_translator_with_symbol); if(it_sym != list.end() && !strcmp((*it_sym)->GetSymbol(), symbolName)) { // Add this translator and patch this import pointer into our translator... (*this->translators.emplace(translators.end(), (*it_sym)->clone()))->Patch(&faddr->u1.Function); } } } } }