From ce49c84f3a26f016f9232d2bffdc830d7fd6169f Mon Sep 17 00:00:00 2001 From: Alexander Lantsev Date: Sat, 30 Aug 2014 11:37:47 +0000 Subject: Tox: - switch to offline when connection is lost - file transfer support - code refactoring - project reordering - version bump git-svn-id: http://svn.miranda-ng.org/main/trunk@10340 1316c22d-e87f-b044-9b9b-93d7a3e3ba9c --- .../Tox/tox/deflibcreator/src/deflibcreator.cpp | 310 +++++++++++++++++++++ 1 file changed, 310 insertions(+) create mode 100644 protocols/Tox/tox/deflibcreator/src/deflibcreator.cpp (limited to 'protocols/Tox/tox/deflibcreator/src/deflibcreator.cpp') diff --git a/protocols/Tox/tox/deflibcreator/src/deflibcreator.cpp b/protocols/Tox/tox/deflibcreator/src/deflibcreator.cpp new file mode 100644 index 0000000000..6480fda7e3 --- /dev/null +++ b/protocols/Tox/tox/deflibcreator/src/deflibcreator.cpp @@ -0,0 +1,310 @@ +#define WIN32_LEAN_AND_MEAN +#define _WIN32_WINNT 0x0501 +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#pragma comment(lib, "dbghelp.lib") +#pragma comment(lib, "shlwapi.lib") +#pragma comment(lib, "shell32.lib") + +// ordinals to names +typedef std::map > ExportMap; + +void GetExports(PVOID pMapping, ExportMap& exports, WORD& imageType) +{ + ULONG size = 0; + PIMAGE_NT_HEADERS pHead = ImageNtHeader(pMapping); + PIMAGE_EXPORT_DIRECTORY pDir = static_cast(ImageDirectoryEntryToData(pMapping, FALSE, IMAGE_DIRECTORY_ENTRY_EXPORT, &size)); + if(pHead && pDir) + { + imageType = pHead->FileHeader.Machine; + char* base = static_cast(pMapping); + DWORD rvaExportDir = reinterpret_cast(pDir) - base; + PIMAGE_SECTION_HEADER pSec = NULL; + PDWORD namesAddr = static_cast(ImageRvaToVa(pHead, pMapping, pDir->AddressOfNames, &pSec)); + PWORD ordinalAddr = static_cast(ImageRvaToVa(pHead, pMapping, pDir->AddressOfNameOrdinals, &pSec)); + DWORD numFuncs = pDir->NumberOfFunctions; + DWORD numNames = pDir->NumberOfNames; + DWORD baseOrd = pDir->Base; + + std::set ordinals; + DWORD lastOrd = baseOrd + numFuncs; + for(DWORD i = baseOrd; i < lastOrd; ++i) + { + ordinals.insert(i); + } + + for(DWORD i = 0; i < numNames; ++i) + { + WORD thisZeroBasedOrd = ordinalAddr[i]; + DWORD thisBasedOrd = thisZeroBasedOrd + baseOrd; + ordinals.erase(thisBasedOrd); + LPCSTR name = static_cast(ImageRvaToVa(pHead, pMapping, namesAddr[i], &pSec)); + exports[thisBasedOrd].push_back(name); + } + + for(std::set::const_iterator iter = ordinals.begin(), end = ordinals.end(); + iter != end; + ++iter + ) + { + exports.insert(std::make_pair(*iter, ExportMap::mapped_type())); + } + } +} + +PVOID MapFile(HANDLE hFile, DWORD fileMapPerm, DWORD mappedPerms) +{ + PVOID base = NULL; + HANDLE hMap = CreateFileMappingW( + hFile, + NULL, + fileMapPerm, + 0, + 0, + NULL + ); + if(hMap) + { + base = MapViewOfFile(hMap, mappedPerms, 0, 0, 0); + CloseHandle(hMap); + } + return base; +} + +PVOID MapFile(const wchar_t* fileName, DWORD filePerms, DWORD fileMapPerm, DWORD mappedPerms) +{ + PVOID base = NULL; + HANDLE hFile = CreateFileW( + fileName, + filePerms, + FILE_SHARE_READ, + NULL, + OPEN_EXISTING, + FILE_ATTRIBUTE_NORMAL | FILE_FLAG_SEQUENTIAL_SCAN, + NULL + ); + if(hFile != INVALID_HANDLE_VALUE) + { + base = MapFile(hFile, fileMapPerm, mappedPerms); + CloseHandle(hFile); + } + return base; +} + +PVOID MapFileRO(const wchar_t* fileName, BOOL image) +{ + return MapFile(fileName, GENERIC_READ, PAGE_READONLY | (image ? SEC_IMAGE : 0), FILE_MAP_READ); +} + +std::wstring GetFileName(const wchar_t* pFilePath) +{ + const wchar_t* pAfterSlash = pFilePath, *pSlash = NULL; + while((pSlash = wcspbrk(pAfterSlash, L"\\/")) != NULL) + { + pAfterSlash = pSlash + 1; + } + const wchar_t* pDot = wcschr(pAfterSlash, L'.'); + if(pDot != NULL) + { + return std::wstring(pAfterSlash, pDot); + } + else return std::wstring(pAfterSlash); +} + +std::wstring MakeWString(const char* string) +{ + size_t reqd = mbstowcs(NULL, string, 0); + if(reqd != static_cast(-1)) + { + std::wstring str(reqd, 0); + mbstowcs(&str[0], string, reqd); + return str; + } + return std::wstring(string, string + strlen(string) + 1); +} + +void DoAndWaitForExecution(SHELLEXECUTEINFO& sei) +{ + if(!ShellExecuteEx(&sei)) + { + std::wcerr << L"Couldn't execute \"" << sei.lpFile << L'\n'; + } + else + { + WaitForSingleObject(sei.hProcess, INFINITE); + CloseHandle(sei.hProcess); + } +} + +void CreateLibs(const std::wstring& defFile, const std::wstring& baseName, const std::wstring& outDir, WORD machineType) +{ + std::wstring curDir(1000, 0); + curDir.resize(GetModuleFileName(GetModuleHandle(NULL), &curDir[0], curDir.length())); + curDir.resize(curDir.find_last_of(L"\\/") + 1); + SHELLEXECUTEINFO sei = {sizeof(sei), 0}; + sei.fMask = SEE_MASK_NOCLOSEPROCESS; + sei.hwnd = GetConsoleWindow(); + sei.lpVerb = L"open"; + sei.lpDirectory = outDir.c_str(); + + // 32-bit libs + if(machineType == IMAGE_FILE_MACHINE_I386) + { + std::wcout << L"Creating 32-bit libs...\n"; + // dlltool for mingw (x86) + std::wcout << L"\tCreating lib" << baseName << L".a...\n"; + std::wostringstream pstream; + pstream << L"-d \"" << defFile << L"\" -l lib" << baseName << L".a"; + + std::wstring binary = curDir + L"dlltool.exe"; + std::wstring parameters = pstream.str(); + + sei.lpFile = binary.c_str(); + sei.lpParameters = parameters.c_str(); + + DoAndWaitForExecution(sei); + + pstream.str(L""); + + // link for msvc (x86) + std::wcout << L"\tCreating " << baseName << L".lib...\n"; + pstream << L"/lib /nologo /machine:x86 /def:\"" << defFile << "\" /out:\"" << outDir << baseName << L".lib\""; + + binary = curDir + L"link.exe"; + parameters = pstream.str(); + sei.lpFile = binary.c_str(); + sei.lpParameters = parameters.c_str(); + DoAndWaitForExecution(sei); + } + else + { + std::wcout << L"Creating 64-bit libs...\n"; + // dlltool for mingw (x64) (my fail if running on 32-bit comp) + std::wcout << L"\tlib" << baseName << L"-x64.a...\n"; + + std::wstring binary = curDir + L"dlltool64.exe"; + std::wstring as64Pos = L"\""; + as64Pos += (curDir + L"as64.exe\""); + std::wostringstream pstream; + pstream << L"-d \"" << defFile << L"\" -S " << as64Pos << L" -l lib" << baseName << L"-x64.a"; + + std::wstring parameters = pstream.str(); + sei.lpFile = binary.c_str(); + sei.lpParameters = parameters.c_str(); + DoAndWaitForExecution(sei); + + pstream.str(L""); + + // link for msvc (x64) + std::wcout << L'\t' << baseName << L"-x64.lib...\n"; + binary = curDir + L"link.exe"; + pstream << L"/lib /nologo /machine:x64 /def:\"" << defFile << "\" /out:\"" << outDir << baseName << L"-x64.lib\""; + parameters = pstream.str(); + sei.lpFile = binary.c_str(); + sei.lpParameters = parameters.c_str(); + DoAndWaitForExecution(sei); + } +} + +BOOL CreateDef(LPCWSTR dllFile, const std::wstring& defFile, WORD& machineType) +{ + std::wcout << L"Creating " << defFile << L"...\n"; + // this is FALSE on purpose. If it's true, some dll's (mainly bcrypt.dll from Vista) + // fail to map as an image because of some funkyness with the certificate or + // something (STATUS_INVALID_IMAGE_HASH fyi). So this is just easier + PVOID pMapping = MapFileRO(dllFile, FALSE); + if(pMapping) + { + ExportMap exports; + GetExports(pMapping, exports, machineType); + if(!exports.empty()) + { + std::wofstream defFile(defFile.c_str()); + std::wostringstream expDetails; + defFile << L"LIBRARY \"" << GetFileName(dllFile) << L"\"\n\nEXPORTS\n"; + for(ExportMap::const_iterator iter = exports.begin(), end = exports.end(); + iter != end; + ++iter + ) + { + expDetails.str(L""); + expDetails.clear(); + expDetails << L'\t'; + const ExportMap::mapped_type& names = iter->second; + if(!names.empty()) + { + const std::wstring& initialName = MakeWString(*(names.begin())); + expDetails << initialName << L"\t@" << iter->first << L'\n'; + for(ExportMap::mapped_type::const_iterator namesIter = names.begin() + 1, namesEnd = names.end(); + namesIter != namesEnd; + ++namesIter + ) + { + expDetails << '\t' << MakeWString(*namesIter) << L'=' << initialName << L'\n'; + } + } + // unnamed export + else + { + expDetails << L"Ordinal" << iter->first << L" NONAME\t@" << iter->first << L'\n'; + } + defFile << expDetails.str(); + } + } + else + { + std::wcerr << dllFile << L" has no exports, nothing to do\n"; + return FALSE; + } + UnmapViewOfFile(pMapping); + } + return TRUE; +} + +int __cdecl wmain(int argc, wchar_t** argv) +{ + std::wcout << L"DefLibCreator v1.0 - Airesoft.co.uk\n\n"; + if(argc < 2) + { + puts("Usage: DefLibCreator dll [outDir]"); + return 1; + } + else + { + std::wstring baseFileName = PathFindFileName(argv[1]); + baseFileName.erase(baseFileName.find_last_of('.')); + int outDirArg = (argc >= 3) ? 2 : 1; + LPWSTR pFilePart = NULL; + std::wstring outDir(GetFullPathName(argv[outDirArg], 0, NULL, NULL), 0); + outDir.resize(GetFullPathName(argv[outDirArg], outDir.length(), &outDir[0], &pFilePart)); + // if the explicit output dir wasn't specified, we need to chop the dll filename off the end of outDir + if(outDirArg == 1) + { + outDir.resize(pFilePart - outDir.c_str()); + } + else + { + CreateDirectory(outDir.c_str(), NULL); + } + outDir.push_back(L'\\'); // ensure it ends with a slash + std::wstring defFile(outDir); + defFile += (baseFileName + L".def"); + WORD machineType = 0; + if(CreateDef(argv[1], defFile, machineType)) + { + CreateLibs(defFile, baseFileName, outDir, machineType); + } + } + return 0; +} -- cgit v1.2.3