// CCEngineLoader.cpp : Defines the entry point for the console application. // #include "CachedDownloader.h" #include "HTTPClient.h" #include "JSONModuleDatabase.h" #include "ModuleManager.h" #include #include #include #include #include namespace pt = boost::property_tree; namespace fs = boost::filesystem; namespace { static const std::string updateCacheFolder = ".upd"; void waitUntilProcessTerminates(unsigned long processID) { HANDLE hProcess = OpenProcess(SYNCHRONIZE, true, processID); if (NULL == hProcess) { WaitForSingleObject(hProcess, INFINITE); } } void runApp(const std::string& cmdLine, bool waitForProcessToExit) { STARTUPINFO si; PROCESS_INFORMATION pi; ZeroMemory(&si, sizeof(si)); si.cb = sizeof(si); ZeroMemory(&pi, sizeof(pi)); // Start the child process. if (!CreateProcess(NULL, // No module name (use command line) (LPSTR)cmdLine.c_str(), // Command line NULL, // Process handle not inheritable NULL, // Thread handle not inheritable FALSE, // Set handle inheritance to FALSE DETACHED_PROCESS, // No creation flags NULL, // Use parent's environment block NULL, // Use parent's starting directory &si, // Pointer to STARTUPINFO structure &pi) // Pointer to PROCESS_INFORMATION structure ) { printf("CreateProcess failed (%d).\n", GetLastError()); return; } if (waitForProcessToExit) { // Wait until child process exits. WaitForSingleObject(pi.hProcess, INFINITE); } // Close process and thread handles. CloseHandle(pi.hProcess); CloseHandle(pi.hThread); } std::vector loadPendingUpdates(const boost::filesystem::path& appDir) { std::vector result; boost::filesystem::path path(appDir / updateCacheFolder / ".updates.json"); if (boost::filesystem::is_regular_file(path)) { pt::ptree root; pt::read_json(path.string(), root); deserialize(root, result); } return result; } } int main(int argc, char* argv[]) { auto appDir = fs::system_complete(argv[0]).parent_path(); unsigned long parentProcessId = 0; if (argc >= 2) { parentProcessId = std::atol(argv[1]); } std::vector moduleUpdates = loadPendingUpdates(appDir); HTTPClient httpClient; CachedDownloader cachedDownloader(appDir / updateCacheFolder, httpClient); JSONModuleDatabase moduleDatabase((appDir / ".inst").string()); ModuleManager moduleManager(appDir.string(), moduleDatabase, cachedDownloader); bool isRestartRequired = false; for (const auto& update : moduleUpdates) { bool restartRequired = update.flag & static_cast(ModuleUpdateFlags::restartRequired); isRestartRequired = isRestartRequired || restartRequired; if (restartRequired && parentProcessId) { std::cout << "RestartRequired" << std::endl; waitUntilProcessTerminates(parentProcessId); parentProcessId = 0; } moduleManager.applyUpdate(update.moduleId, update); std::cout << "UpdateApplied " << update.moduleId << " " << update.version << std::endl; } std::cout << "Done" << std::endl; if (isRestartRequired) { runApp((appDir / "CCEngine.exe").string() + " --updated", false); } return 0; }