OSDN Git Service

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