//////////////////////////////////////////////////////////////////////////// // DllLoader.cpp : implementation and testing for DllLoader.h // // ver 1.1 // // // // Application : OOD F18 Project 2 Help // // Platform : VS17 Community - Windows 10 Professional x64 // // Author : Ammar Salman, EECS Department, Syracuse University // // 313/788-4694, hoplite.90@hotmail.com // //////////////////////////////////////////////////////////////////////////// #include "DllLoader.h" using namespace std; // a function to convert std::string to std::wstring (Windows.h uses a // different string format) std::wstring s2ws(const std::string& s) { int len; int slength = (int)s.length() + 1; len = MultiByteToWideChar(CP_ACP, 0, s.c_str(), slength, 0, 0); wchar_t* buf = new wchar_t[len]; MultiByteToWideChar(CP_ACP, 0, s.c_str(), slength, buf, len); std::wstring r(buf); delete[] buf; return r; } //----< alternate string converter using std C++ >------------------- std::wstring toWstring(const std::string& s) { std::wstring wstr; for (auto ch : s) { wstr += (wchar_t)ch; } return wstr; // will move } DllLoader::DllLoader(){} DllLoader::~DllLoader() { clear(); // to make sure the DLL is unloaded } // accepts a DLL path and attempts to load it and extract its tests bool DllLoader::loadAndExtract(const std::string & dll) { /////////////////////////////////////////////////////// // all of these work - Fawcett //---------------------------------------------------- // hmod = LoadLibrary(s2ws(dll).c_str()); // load DLL // hmod = LoadLibraryA(dll.c_str()); // load DLL hmod = LoadLibraryW(toWstring(dll).c_str()); // load DLL if (!hmod) return false; // check if DLL was properly loaded // check if the DLL contains get_ITests() function ... // in other words, check if the DLL complies with the protocol //typedef ITests* (*gITs)(); using gITs = ITests * (*)(); // using instead of typedef gITs get_ITests = (gITs)GetProcAddress(hmod, "get_ITests"); if (!get_ITests) return false; // execute get_ITests() to get the collection of tests ITests* tests = get_ITests(); if (tests) { // check if tests is nullptr before attempting to get its tests collection std::vector extTsts = tests->tests(); extractedTests.insert(extractedTests.begin(), extTsts.begin(), extTsts.end()); return true; } // this will only be reached if get_ITests() returned nullptr in which case the // TestDriver DLL contains no tests to execute. return false; } const std::vector& DllLoader::tests() const { return extractedTests; } void DllLoader::clear() { if (hmod) FreeLibrary(hmod); extractedTests.clear(); } #ifdef TEST_DLL_LOADER #include #include int main() { cout << "\n Testing DLL Loader"; cout << "\n ===================="; DllLoader loader; cout << "\n\n Loading '../Debug/TestDriver1.dll' which is a single-test TestDriver..."; bool loaded = loader.loadAndExtract("../Debug/TestDriver1.dll"); if (!loaded) { cout << " failed to load dll or failed to load tests.\n Terminating...\n"; return -1; } cout << " successfully loaded"; cout << "\n Extracted tests:"; for (auto test : loader.tests()) { cout << "\n Test name: " << setw(30) << left << test->name() << " - Author: " << setw(20) << test->author(); cout << "\n Executing test..."; bool res = test->test(); cout << "\n\n Test passed: " << to_string(res); } cout << "\n\n Loading '../Debug/TestDriver2.dll' which is a multiple-tests TestDriver ..."; loader.clear(); loaded = loader.loadAndExtract("../Debug/TestDriver2.dll"); if (!loaded) { cout << " failed to load dll or failed to load tests.\n Terminating...\n"; return -1; } cout << " successfully loaded"; cout << "\n Extracted tests:"; for (auto test : loader.tests()) { cout << "\n Test name: " << setw(30) << left << test->name() << " - Author: " << setw(20) << test->author(); cout << "\n Executing test..."; bool res = test->test(); cout << "\n\n Test passed: " << to_string(res); } cout << "\n\n"; return 0; } #endif