OSDN Git Service

Merge pull request #16 from Lippe35/master
[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 <sstream>
12 #include <Poco/Path.h>
13 #include <Poco/Process.h>
14 #include "paths.h"
15 #include "unicoder.h"
16
17 using Poco::Path;
18 using Poco::Process;
19
20 namespace env
21 {
22
23 /**
24  * @brief Temp path.
25  * Static string used by GetTemporaryPath() for storing temp path.
26  */
27 static String strTempPath;
28 static String strProgPath;
29
30 void SetTemporaryPath(const String& path)
31 {
32         strTempPath = paths::AddTrailingSlash(paths::GetLongPath(path));
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 GetTemporaryPath()
44 {
45         if (strTempPath.empty())
46         {
47                 strTempPath = 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 GetTemporaryFileName(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 GetTempChildPath()
80 {
81         String path;
82         do
83         {
84                 path = paths::ConcatPath(GetTemporaryPath(), strutils::format(_T("%08x"), rand()));
85         } while (paths::IsDirectory(path) || !paths::CreateIfNeeded(path));
86         return path;
87 }
88
89 void SetProgPath(const String& path)
90 {
91         strProgPath = paths::AddTrailingSlash(path);
92 }
93
94 String GetProgPath()
95 {
96         if (strProgPath.empty())
97         {
98                 TCHAR temp[MAX_PATH] = {0};
99                 GetModuleFileName(NULL, temp, MAX_PATH);
100                 strProgPath = paths::GetPathOnly(temp);
101         }
102         return strProgPath;
103 }
104
105 /**
106  * @brief Get Windows directory.
107  * @return Windows directory.
108  */
109 String GetWindowsDirectory()
110 {
111         TCHAR path[MAX_PATH];
112         path[0] = _T('\0');
113         ::GetWindowsDirectory(path, MAX_PATH);
114         return path;
115 }
116
117 /**
118  * @brief Return User's My Documents Folder.
119  * This function returns full path to User's My Documents -folder.
120  * @return Full path to My Documents -folder.
121  */
122 String GetMyDocuments()
123 {
124         TCHAR path[MAX_PATH];
125         path[0] = _T('\0');
126         SHGetFolderPath(NULL, CSIDL_PERSONAL, NULL, 0, path);
127         return path;
128 }
129
130 /**
131  * @brief Return unique string for the instance.
132  * This function formats an unique string for WinMerge instance. The string
133  * is quaranteed to be unique for instance asking it.
134  * @param [in] name Additional name used as part of the string.
135  * @return Unique string for the instance.
136  */
137 String GetPerInstanceString(const String& name)
138 {
139         std::basic_stringstream<TCHAR> stream;
140         stream << name << Process::id();
141         return stream.str();
142 }
143
144 /**
145  * @brief Get system temporary directory.
146  * @return System temporary director.
147  */
148 String GetSystemTempPath()
149 {
150         try
151         {
152                 return ucr::toTString(Path::temp());
153         }
154         catch (...)
155         {
156                 return _T("");
157         }
158 }
159
160 static bool launchProgram(const String& sCmd, WORD wShowWindow)
161 {
162         STARTUPINFO stInfo = { sizeof(STARTUPINFO) };
163         stInfo.dwFlags = STARTF_USESHOWWINDOW;
164         stInfo.wShowWindow = wShowWindow;
165         PROCESS_INFORMATION processInfo;
166         BOOL retVal = CreateProcess(NULL, (LPTSTR)sCmd.c_str(),
167                 NULL, NULL, FALSE, CREATE_DEFAULT_ERROR_MODE, NULL, NULL,
168                 &stInfo, &processInfo);
169         if (!retVal)
170                 return false;
171         CloseHandle(processInfo.hThread);
172         CloseHandle(processInfo.hProcess);
173         return true;
174 }
175
176 /**
177  * @brief Load registry keys from .reg file if existing .reg file
178  */
179 bool LoadRegistryFromFile(const String& sRegFilePath)
180 {
181         if (paths::DoesPathExist(sRegFilePath) != paths::IS_EXISTING_FILE)
182                 return false;
183         return launchProgram(_T("reg.exe import \"") + sRegFilePath + _T("\""), SW_HIDE);
184 }
185
186 /** 
187  * @brief Save registry keys to .reg file if existing .reg file
188  */
189 bool SaveRegistryToFile(const String& sRegFilePath, const String& sRegDir)
190 {
191         if (paths::DoesPathExist(sRegFilePath) != paths::IS_EXISTING_FILE)
192                 return false;
193         DeleteFile(sRegFilePath.c_str());
194         return launchProgram(_T("reg.exe export HKCU\\") + sRegDir + _T(" \"") + sRegFilePath + _T("\""), SW_HIDE);
195 }
196
197 }