OSDN Git Service

Merge with stable
[winmerge-jp/winmerge-jp.git] / Src / Environment.cpp
1 /** 
2  * @file  Environment.cpp
3  *
4  * @brief Environment related routines.
5  */
6
7 #define POCO_NO_UNWINDOWS 1
8 #include "Environment.h"
9 #include <windows.h>
10 #include <shlobj.h>
11 #include <cassert>
12 #include <sstream>
13 #include <Poco/Path.h>
14 #include <Poco/Process.h>
15 #include "paths.h"
16 #include "unicoder.h"
17
18 using Poco::Path;
19 using Poco::Process;
20
21 /**
22  * @brief Temp path.
23  * Static string used by env_GetTempPath() for storing temp path.
24  */
25 static String strTempPath;
26 static String strProgPath;
27
28 void env_SetTempPath(const String& path)
29 {
30         strTempPath = paths_AddTrailingSlash(path);
31         paths_CreateIfNeeded(strTempPath);
32 }
33
34 /** 
35  * @brief Get folder for temporary files.
36  * This function returns system temp folder.
37  * @return Temp path, or empty string if error happened.
38  * @note Temp path is cached after first call.
39  * @todo Should we return NULL for error case?
40  */
41 String env_GetTempPath()
42 {
43         if (strTempPath.empty())
44         {
45                 strTempPath = env_GetSystemTempPath();
46                 if (strTempPath.empty())
47                         return strTempPath;
48
49                 paths_CreateIfNeeded(strTempPath);
50         }
51         return strTempPath;
52 }
53
54 /**
55  * @brief Get filename for temporary file.
56  * @param [in] lpPathName Temporary file folder.
57  * @param [in] lpPrefixString Prefix to use for filename.
58  * @param [out] pnerr Error code if error happened.
59  * @return Full path for temporary file or empty string if error happened.
60  */
61 String env_GetTempFileName(const String& lpPathName, const String& lpPrefixString, int * pnerr)
62 {
63         TCHAR buffer[MAX_PATH] = {0};
64         if (lpPathName.length() > MAX_PATH-14)
65                 return _T(""); // failure
66         int rtn = GetTempFileName(lpPathName.c_str(), lpPrefixString.c_str(), 0, buffer);
67         if (!rtn)
68         {
69                 int err = GetLastError();
70                 if (pnerr)
71                         *pnerr = err;
72                 return _T("");
73         }
74         return buffer;
75 }
76
77 String env_GetTempChildPath()
78 {
79         String path;
80         do
81         {
82                 path = paths_ConcatPath(env_GetTempPath(), string_format(_T("%08x"), rand()));
83         } while (paths_IsDirectory(path) || !paths_CreateIfNeeded(path));
84         return path;
85 }
86
87 void env_SetProgPath(const String& path)
88 {
89         strProgPath = paths_AddTrailingSlash(path);
90 }
91
92 String env_GetProgPath()
93 {
94         if (strProgPath.empty())
95         {
96                 TCHAR temp[MAX_PATH] = {0};
97                 GetModuleFileName(NULL, temp, MAX_PATH);
98                 strProgPath = paths_GetPathOnly(temp);
99         }
100         return strProgPath;
101 }
102
103 /**
104  * @brief Get Windows directory.
105  * @return Windows directory.
106  */
107 String env_GetWindowsDirectory()
108 {
109         TCHAR buf[MAX_PATH] = {0};
110         GetWindowsDirectory(buf, MAX_PATH);
111         return buf;
112 }
113
114 /**
115  * @brief Return User's My Documents Folder.
116  * This function returns full path to User's My Documents -folder.
117  * @return Full path to My Documents -folder.
118  */
119 String env_GetMyDocuments()
120 {
121         LPITEMIDLIST pidl;
122         LPMALLOC pMalloc;
123         String path;
124
125         HRESULT rv = SHGetSpecialFolderLocation(NULL, CSIDL_PERSONAL, &pidl);
126         if (rv == S_OK)
127         {
128                 TCHAR szPath[MAX_PATH] = {0};
129                 if (SHGetPathFromIDList(pidl, szPath))
130                 {
131                         path = szPath;
132                 }
133
134                 SHGetMalloc(&pMalloc);
135                 pMalloc->Free(pidl);
136                 pMalloc->Release();
137         }
138         return path;
139 }
140
141 /**
142  * @brief Return unique string for the instance.
143  * This function formats an unique string for WinMerge instance. The string
144  * is quaranteed to be unique for instance asking it.
145  * @param [in] name Additional name used as part of the string.
146  * @return Unique string for the instance.
147  */
148 String env_GetPerInstanceString(const String& name)
149 {
150         std::basic_stringstream<TCHAR> stream;
151         stream << name << Process::id();
152         return stream.str();
153 }
154
155 /**
156  * @brief Get system temporary directory.
157  * @return System temporary director.
158  */
159 String env_GetSystemTempPath()
160 {
161         try
162         {
163                 return ucr::toTString(Path::temp());
164         }
165         catch (...)
166         {
167                 return _T("");
168         }
169 }
170
171 static bool launchProgram(const String& sCmd, WORD wShowWindow)
172 {
173         STARTUPINFO stInfo = {0};
174         stInfo.cb = sizeof(STARTUPINFO);
175         stInfo.dwFlags = STARTF_USESHOWWINDOW;
176         stInfo.wShowWindow = wShowWindow;
177         PROCESS_INFORMATION processInfo;
178         BOOL retVal = CreateProcess(NULL, (LPTSTR)sCmd.c_str(),
179                 NULL, NULL, FALSE, CREATE_DEFAULT_ERROR_MODE, NULL, NULL,
180                 &stInfo, &processInfo);
181         if (!retVal)
182                 return false;
183         CloseHandle(processInfo.hThread);
184         CloseHandle(processInfo.hProcess);
185         return true;
186 }
187
188 /**
189  * @brief Load registry keys from .reg file if existing .reg file
190  */
191 bool env_LoadRegistryFromFile(const String& sRegFilePath)
192 {
193         if (paths_DoesPathExist(sRegFilePath) != IS_EXISTING_FILE)
194                 return false;
195         return launchProgram(_T("reg.exe import \"") + sRegFilePath + _T("\""), SW_HIDE);
196 }
197
198 /** 
199  * @brief Save registry keys to .reg file if existing .reg file
200  */
201 bool env_SaveRegistryToFile(const String& sRegFilePath, const String& sRegDir)
202 {
203         if (paths_DoesPathExist(sRegFilePath) != IS_EXISTING_FILE)
204                 return false;
205         DeleteFile(sRegFilePath.c_str());
206         return launchProgram(_T("reg.exe export HKCU\\") + sRegDir + _T(" \"") + sRegFilePath + _T("\""), SW_HIDE);
207 }