diff --git a/include/resource_dumper.h b/include/resource_dumper.h index 327a75b..9799c6b 100644 --- a/include/resource_dumper.h +++ b/include/resource_dumper.h @@ -66,7 +66,7 @@ private: uint32_t AddPairVauleToJson(const ResourceItem &item, cJSON *json) const; uint32_t AddKeyParamsToJson(const std::vector &keyParams, cJSON *json) const; uint32_t AddResourceToJson(int64_t id, const std::vector &items, cJSON *json) const; - uint32_t AddItemCommonPropToJson(int32_t resId, const ResourceItem &item, cJSON* json) const; + uint32_t AddItemCommonPropToJson(int64_t resId, const ResourceItem &item, cJSON* json) const; }; } // namespace Restool diff --git a/include/restool_errors.h b/include/restool_errors.h index 3bcb79d..b218903 100644 --- a/include/restool_errors.h +++ b/include/restool_errors.h @@ -29,6 +29,7 @@ namespace Restool { constexpr uint32_t RESTOOL_SUCCESS = 0; constexpr uint32_t RESTOOL_ERROR = -1; constexpr uint16_t BUFFER_SIZE = 4096; +constexpr uint16_t BUFFER_SIZE_SMALL = 128; const std::string ERROR_MORE_INFO_FILE = "restool_faq.json"; // 11200xxx unknown error constexpr uint32_t ERR_CODE_UNDEFINED_ERROR = 11200000; diff --git a/src/resource_dumper.cpp b/src/resource_dumper.cpp index 7cb3b0a..4778129 100644 --- a/src/resource_dumper.cpp +++ b/src/resource_dumper.cpp @@ -194,7 +194,7 @@ uint32_t CommonDumper::AddKeyParamsToJson(const std::vector &keyParams return RESTOOL_SUCCESS; } -uint32_t CommonDumper::AddItemCommonPropToJson(int32_t resId, const ResourceItem &item, cJSON* json) const +uint32_t CommonDumper::AddItemCommonPropToJson(int64_t resId, const ResourceItem &item, cJSON* json) const { if (!json) { PrintError(GetError(ERR_CODE_UNDEFINED_ERROR).FormatCause("add item common property to null json object")); diff --git a/src/restool.cpp b/src/restool.cpp index dfe9ae0..4aab32f 100644 --- a/src/restool.cpp +++ b/src/restool.cpp @@ -30,7 +30,11 @@ int main(int argc, char *argv[]) PrintError(GetError(ERR_CODE_UNKNOWN_COMMAND_ERROR).FormatCause("argv null")); return RESTOOL_ERROR; } - InitFaq(std::string(argv[0])); + try { + InitFaq(std::string(argv[0])); + } catch (const std::runtime_error &error) { + return RESTOOL_ERROR; + } auto &parser = CmdParser::GetInstance(); return parser.Parse(argc, argv, 1); } diff --git a/src/restool_errors.cpp b/src/restool_errors.cpp index e3e63d8..bcb572c 100644 --- a/src/restool_errors.cpp +++ b/src/restool_errors.cpp @@ -15,6 +15,13 @@ #include #include +#ifdef __WIN32 +#include +#else +#include +#include +#include +#endif #include "resource_util.h" #include "restool_errors.h" @@ -525,33 +532,132 @@ const std::map ERRORS_MAP = { #ifdef __WIN32 constexpr int WIN_LOCALE_CN = 2052; #endif +const std::string LOCALE_CMD_WIN = "wmic os get locale"; +const std::string LOCALE_CMD_LINUX = "locale"; +const std::string LOCALE_CMD_MAC = "defaults read -globalDomain AppleLocale"; const std::string LOCALE_CN = "zh_CN"; std::map faqInfos; MoreInfo defaultMoreInfo = {}; Language osLanguage = Language::EN; +bool IsValidCmd(const std::string &cmd) +{ + if (cmd == LOCALE_CMD_WIN || cmd == LOCALE_CMD_LINUX || cmd == LOCALE_CMD_MAC) { + return true; + } + return false; +} + +#ifdef __WIN32 +std::string ExecuteCommand(const std::string &cmd) +{ + if (!IsValidCmd(cmd)) { + return ""; + } + SECURITY_ATTRIBUTES saAttr; + saAttr.nLength = sizeof(SECURITY_ATTRIBUTES); + saAttr.bInheritHandle = TRUE; + saAttr.lpSecurityDescriptor = NULL; + HANDLE hReadPipe; + HANDLE hWritePipe; + if (!CreatePipe(&hReadPipe, &hWritePipe, &saAttr, 0)) { + return "CreatePipe failed"; + } + STARTUPINFO si; + PROCESS_INFORMATION pi; + ZeroMemory(&si, sizeof(si)); + si.cb = sizeof(si); + si.hStdError = hWritePipe; + si.hStdOutput = hWritePipe; + si.hStdInput = GetStdHandle(STD_INPUT_HANDLE); + si.dwFlags |= STARTF_USESTDHANDLES; + ZeroMemory(&pi, sizeof(pi)); + + if (!CreateProcess(NULL, const_cast(cmd.c_str()), NULL, NULL, TRUE, 0, NULL, NULL, &si, &pi)) { + CloseHandle(hReadPipe); + CloseHandle(hWritePipe); + return "CreateProcess failed"; + } + // close the write end of the pipe in the parent process + CloseHandle(hWritePipe); + std::string result; + DWORD bytesRead; + CHAR buffer[BUFFER_SIZE_SMALL]; + while (ReadFile(hReadPipe, buffer, sizeof(buffer) - 1, &bytesRead, NULL) && bytesRead != 0) { + buffer[bytesRead] = '\0'; + result += buffer; + } + WaitForSingleObject(pi.hProcess, INFINITE); + CloseHandle(hReadPipe); + CloseHandle(pi.hProcess); + CloseHandle(pi.hThread); + return result; +} +#else +std::vector split(const std::string &s, const char &delimiter) +{ + std::vector tokens; + std::string token; + std::stringstream tokenStream(s); + while (std::getline(tokenStream, token, delimiter)) { tokens.push_back(token); } + return tokens; +} + std::string ExecuteCommand(const std::string &cmd) { std::string result; - FILE *pipe = popen(cmd.c_str(), "r"); - if (!pipe) { + if (!IsValidCmd(cmd)) { return result; } - char buffer[BUFFER_SIZE]; - while (!feof(pipe)) { - if (fgets(buffer, BUFFER_SIZE, pipe) != NULL) { + int pipefd[2]; + pid_t pid; + if (pipe(pipefd) == -1) { + perror("open pipe failed"); + return result; + } + pid = fork(); + if (pid == -1) { + perror("fork failed"); + return result; + } + if (pid == 0) { + // child process + close(pipefd[0]); + dup2(pipefd[1], STDOUT_FILENO); + close(pipefd[1]); + std::vector cmds = split(cmd, ' '); + char *argv[cmds.size() + 1]; + size_t i = 0; + for (i = 0; i < cmds.size(); ++i) { + argv[i] = cmds[i].data(); + } + argv[i] = nullptr; + execvp(argv[0], argv); + // if execvp returns, there was an error. + perror("execvp failed"); + throw std::runtime_error("execvp failed"); + } else { + // parent process + // close unused write end + close(pipefd[1]); + char buffer[BUFFER_SIZE_SMALL]; + ssize_t readBytes; + while ((readBytes = read(pipefd[0], buffer, sizeof(buffer) - 1)) > 0) { + buffer[readBytes] = '\0'; result += buffer; } + close(pipefd[0]); + wait(nullptr); } - pclose(pipe); return result; } +#endif #ifdef __WIN32 Language GetWinLanguage() { - std::string result = ExecuteCommand("wmic os get locale"); + std::string result = ExecuteCommand(LOCALE_CMD_WIN); size_t pos = 0; std::string locale = "Locale"; if ((pos = result.find(locale)) != std::string::npos) { @@ -574,18 +680,9 @@ Language GetWinLanguage() #endif #ifdef __LINUX__ -std::vector split(const std::string &s, const char &delimiter) -{ - std::vector tokens; - std::string token; - std::stringstream tokenStream(s); - while (std::getline(tokenStream, token, delimiter)) { tokens.push_back(token); } - return tokens; -} - Language GetLinuxLanguage() { - std::string result = ExecuteCommand("locale"); + std::string result = ExecuteCommand(LOCALE_CMD_LINUX); if (result.empty()) { return Language::CN; } @@ -609,7 +706,7 @@ Language GetLinuxLanguage() #ifdef __MAC__ Language GetMacLanguage() { - std::string result = ExecuteCommand("defaults read -globalDomain AppleLocale"); + std::string result = ExecuteCommand(LOCALE_CMD_MAC); if (result.empty()) { return Language::CN; }