2 * @file Environment.cpp
4 * @brief Environment related routines.
8 #define POCO_NO_UNWINDOWS 1
9 #include "Environment.h"
11 #pragma warning (push) // prevent "warning C4091: 'typedef ': ignored on left of 'tagGPFIDL_FLAGS' when no variable is declared"
12 #pragma warning (disable:4091) // VC bug when using XP enabled toolsets.
16 #include <Poco/Path.h>
17 #include <Poco/Process.h>
29 * Static string used by GetTemporaryPath() for storing temp path.
31 static String strTempPath;
32 static String strProgPath;
34 void SetTemporaryPath(const String& path)
36 strTempPath = paths::AddTrailingSlash(paths::GetLongPath(path));
37 paths::CreateIfNeeded(strTempPath);
41 * @brief Get folder for temporary files.
42 * This function returns system temp folder.
43 * @return Temp path, or empty string if error happened.
44 * @note Temp path is cached after first call.
45 * @todo Should we return `nullptr` for error case?
47 String GetTemporaryPath()
49 if (strTempPath.empty())
51 strTempPath = GetSystemTempPath();
52 if (strTempPath.empty())
55 paths::CreateIfNeeded(strTempPath);
61 * @brief Get filename for temporary file.
62 * @param [in] lpPathName Temporary file folder.
63 * @param [in] lpPrefixString Prefix to use for filename.
64 * @param [out] pnerr Error code if error happened.
65 * @return Full path for temporary file or empty string if error happened.
67 String GetTemporaryFileName(const String& lpPathName, const String& lpPrefixString, int * pnerr /*= nullptr*/)
69 TCHAR buffer[MAX_PATH] = {0};
70 if (lpPathName.length() > MAX_PATH-14)
71 return _T(""); // failure
72 int rtn = ::GetTempFileName(lpPathName.c_str(), lpPrefixString.c_str(), 0, buffer);
75 paths::CreateIfNeeded(lpPathName);
76 rtn = ::GetTempFileName(lpPathName.c_str(), lpPrefixString.c_str(), 0, buffer);
79 int err = GetLastError();
88 String GetTempChildPath()
93 path = paths::ConcatPath(GetTemporaryPath(), strutils::format(_T("%08x"), rand()));
94 } while (paths::IsDirectory(path) || !paths::CreateIfNeeded(path));
98 void SetProgPath(const String& path)
100 strProgPath = paths::AddTrailingSlash(path);
105 if (strProgPath.empty())
107 TCHAR temp[MAX_PATH] = {0};
108 GetModuleFileName(nullptr, temp, MAX_PATH);
109 strProgPath = paths::GetPathOnly(temp);
115 * @brief Get Windows directory.
116 * @return Windows directory.
118 String GetWindowsDirectory()
120 TCHAR path[MAX_PATH];
122 ::GetWindowsDirectory(path, MAX_PATH);
127 * @brief Return User's My Documents Folder.
128 * This function returns full path to User's My Documents -folder.
129 * @return Full path to My Documents -folder.
131 String GetMyDocuments()
133 TCHAR path[MAX_PATH];
135 SHGetFolderPath(nullptr, CSIDL_PERSONAL, nullptr, 0, path);
140 * @brief Return unique string for the instance.
141 * This function formats an unique string for WinMerge instance. The string
142 * is quaranteed to be unique for instance asking it.
143 * @param [in] name Additional name used as part of the string.
144 * @return Unique string for the instance.
146 String GetPerInstanceString(const String& name)
148 std::basic_stringstream<TCHAR> stream;
149 stream << name << Process::id();
154 * @brief Get system temporary directory.
155 * @return System temporary director.
157 String GetSystemTempPath()
161 return ucr::toTString(Path::temp());
169 static bool launchProgram(const String& sCmd, WORD wShowWindow)
171 STARTUPINFO stInfo = { sizeof(STARTUPINFO) };
172 stInfo.dwFlags = STARTF_USESHOWWINDOW;
173 stInfo.wShowWindow = wShowWindow;
174 PROCESS_INFORMATION processInfo;
175 bool retVal = !!CreateProcess(nullptr, (LPTSTR)sCmd.c_str(),
176 nullptr, nullptr, FALSE, CREATE_DEFAULT_ERROR_MODE, nullptr, nullptr,
177 &stInfo, &processInfo);
180 CloseHandle(processInfo.hThread);
181 CloseHandle(processInfo.hProcess);
185 String ExpandEnvironmentVariables(const String& text)
189 const unsigned size = sizeof(buf) / sizeof(buf[0]);
190 const unsigned expandedSize = ::ExpandEnvironmentStrings(text.c_str(), buf, size);
191 if (expandedSize <= size)
193 std::vector<TCHAR> newbuf(expandedSize);
194 ::ExpandEnvironmentStrings(text.c_str(), newbuf.data(), expandedSize);
195 return newbuf.data();
199 * @brief Load registry keys from .reg file if existing .reg file
201 bool LoadRegistryFromFile(const String& sRegFilePath)
203 if (paths::DoesPathExist(sRegFilePath) != paths::IS_EXISTING_FILE)
205 return launchProgram(_T("reg.exe import \"") + sRegFilePath + _T("\""), SW_HIDE);
209 * @brief Save registry keys to .reg file if existing .reg file
211 bool SaveRegistryToFile(const String& sRegFilePath, const String& sRegDir)
213 if (paths::DoesPathExist(sRegFilePath) != paths::IS_EXISTING_FILE)
215 DeleteFile(sRegFilePath.c_str());
216 return launchProgram(_T("reg.exe export HKCU\\") + sRegDir + _T(" \"") + sRegFilePath + _T("\""), SW_HIDE);