/* * Copyright (c) 2019, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License version 2 only, as * published by the Free Software Foundation. Oracle designates this * particular file as subject to the "Classpath" exception as provided * by Oracle in the LICENSE file that accompanied this code. * * This code is distributed in the hope that it will be useful, but WITHOUT * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License * version 2 for more details (a copy is included in the LICENSE file that * accompanied this code). * * You should have received a copy of the GNU General Public License version * 2 along with this work; if not, write to the Free Software Foundation, * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. * * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA * or visit www.oracle.com if you need additional information or have any * questions. */ #include #include #include "WinSysInfo.h" #include "FileUtils.h" #include "WinErrorHandling.h" #pragma comment(lib, "Shell32") namespace SysInfo { tstring getTempDir() { std::vector buffer(MAX_PATH); DWORD res = GetTempPath(static_cast(buffer.size()), buffer.data()); if (res > buffer.size()) { buffer.resize(res); GetTempPath(static_cast(buffer.size()), buffer.data()); } return FileUtils::removeTrailingSlash(buffer.data()); } namespace { template tstring getSystemDirImpl(Func func, const std::string& label) { std::vector buffer(MAX_PATH); for (int i=0; i<2; i++) { DWORD res = func(buffer.data(), static_cast(buffer.size())); if (!res) { JP_THROW(SysError(label + " failed", func)); } if (res < buffer.size()) { return FileUtils::removeTrailingSlash(buffer.data()); } buffer.resize(res + 1); } JP_THROW("Unexpected reply from" + label); } } // namespace tstring getSystem32Dir() { return getSystemDirImpl(GetSystemDirectory, "GetSystemDirectory"); } tstring getWIPath() { return FileUtils::mkpath() << getSystem32Dir() << _T("msiexec.exe"); } namespace { tstring getModulePath(HMODULE h) { std::vector buf(MAX_PATH); DWORD len = 0; while (true) { len = GetModuleFileName(h, buf.data(), (DWORD)buf.size()); if (len < buf.size()) { break; } // buffer is too small, increase it buf.resize(buf.size() * 2); } if (len == 0) { // error occured JP_THROW(SysError("GetModuleFileName failed", GetModuleFileName)); } return tstring(buf.begin(), buf.begin() + len); } } // namespace tstring getProcessModulePath() { return getModulePath(NULL); } HMODULE getCurrentModuleHandle() { // get module handle for the address of this function LPCWSTR address = reinterpret_cast(getCurrentModuleHandle); HMODULE hmodule = NULL; if (!GetModuleHandleExW(GET_MODULE_HANDLE_EX_FLAG_FROM_ADDRESS | GET_MODULE_HANDLE_EX_FLAG_UNCHANGED_REFCOUNT, address, &hmodule)) { JP_THROW(SysError(tstrings::any() << "GetModuleHandleExW failed", GetModuleHandleExW)); } return hmodule; } tstring getCurrentModulePath() { return getModulePath(getCurrentModuleHandle()); } tstring_array getCommandArgs(CommandArgProgramNameMode progNameMode) { int argc = 0; tstring_array result; LPWSTR *parsedArgs = CommandLineToArgvW(GetCommandLineW(), &argc); if (parsedArgs == NULL) { JP_THROW(SysError("CommandLineToArgvW failed", CommandLineToArgvW)); } // the 1st element contains program name for (int i = progNameMode == ExcludeProgramName ? 1 : 0; i < argc; i++) { result.push_back(parsedArgs[i]); } LocalFree(parsedArgs); return result; } namespace { tstring getEnvVariableImpl(const tstring& name, bool* errorOccured=0) { std::vector buf(10); SetLastError(ERROR_SUCCESS); const DWORD size = GetEnvironmentVariable(name.c_str(), buf.data(), DWORD(buf.size())); if (GetLastError() == ERROR_ENVVAR_NOT_FOUND) { if (errorOccured) { *errorOccured = true; return tstring(); } JP_THROW(SysError(tstrings::any() << "GetEnvironmentVariable(" << name << ") failed. Variable not set", GetEnvironmentVariable)); } if (size > buf.size()) { buf.resize(size); GetEnvironmentVariable(name.c_str(), buf.data(), DWORD(buf.size())); if (GetLastError() != ERROR_SUCCESS) { if (errorOccured) { *errorOccured = true; return tstring(); } JP_THROW(SysError(tstrings::any() << "GetEnvironmentVariable(" << name << ") failed", GetEnvironmentVariable)); } } if (errorOccured) { *errorOccured = false; } return tstring(buf.data()); } } // namespace tstring getEnvVariable(const tstring& name) { return getEnvVariableImpl(name); } tstring getEnvVariable(const std::nothrow_t&, const tstring& name, const tstring& defValue) { bool errorOccured = false; const tstring reply = getEnvVariableImpl(name, &errorOccured); if (errorOccured) { return defValue; } return reply; } bool isEnvVariableSet(const tstring& name) { TCHAR unused[1]; SetLastError(ERROR_SUCCESS); GetEnvironmentVariable(name.c_str(), unused, _countof(unused)); return GetLastError() != ERROR_ENVVAR_NOT_FOUND; } } // end of namespace SysInfo