OSDN Git Service

Merge pull request #97 from GreyMerlin/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 #pragma warning (push)                  // prevent "warning C4091: 'typedef ': ignored on left of 'tagGPFIDL_FLAGS' when no variable is declared"
11 #pragma warning (disable:4091)  // VC bug when using XP enabled toolsets.
12 #include <shlobj.h>
13 #pragma warning (pop)
14 #include <sstream>
15 #include <Poco/Path.h>
16 #include <Poco/Process.h>
17 #include "paths.h"
18 #include "unicoder.h"
19
20 using Poco::Path;
21 using Poco::Process;
22
23 namespace env
24 {
25
26 /**
27  * @brief Temp path.
28  * Static string used by GetTemporaryPath() for storing temp path.
29  */
30 static String strTempPath;
31 static String strProgPath;
32
33 void SetTemporaryPath(const String& path)
34 {
35         strTempPath = paths::AddTrailingSlash(paths::GetLongPath(path));
36         paths::CreateIfNeeded(strTempPath);
37 }
38
39 /** 
40  * @brief Get folder for temporary files.
41  * This function returns system temp folder.
42  * @return Temp path, or empty string if error happened.
43  * @note Temp path is cached after first call.
44  * @todo Should we return NULL for error case?
45  */
46 String GetTemporaryPath()
47 {
48         if (strTempPath.empty())
49         {
50                 strTempPath = GetSystemTempPath();
51                 if (strTempPath.empty())
52                         return strTempPath;
53
54                 paths::CreateIfNeeded(strTempPath);
55         }
56         return strTempPath;
57 }
58
59 /**
60  * @brief Get filename for temporary file.
61  * @param [in] lpPathName Temporary file folder.
62  * @param [in] lpPrefixString Prefix to use for filename.
63  * @param [out] pnerr Error code if error happened.
64  * @return Full path for temporary file or empty string if error happened.
65  */
66 String GetTemporaryFileName(const String& lpPathName, const String& lpPrefixString, int * pnerr)
67 {
68         TCHAR buffer[MAX_PATH] = {0};
69         if (lpPathName.length() > MAX_PATH-14)
70                 return _T(""); // failure
71         int rtn = ::GetTempFileName(lpPathName.c_str(), lpPrefixString.c_str(), 0, buffer);
72         if (!rtn)
73         {
74                 int err = GetLastError();
75                 if (pnerr)
76                         *pnerr = err;
77                 return _T("");
78         }
79         return buffer;
80 }
81
82 String GetTempChildPath()
83 {
84         String path;
85         do
86         {
87                 path = paths::ConcatPath(GetTemporaryPath(), strutils::format(_T("%08x"), rand()));
88         } while (paths::IsDirectory(path) || !paths::CreateIfNeeded(path));
89         return path;
90 }
91
92 void SetProgPath(const String& path)
93 {
94         strProgPath = paths::AddTrailingSlash(path);
95 }
96
97 String GetProgPath()
98 {
99         if (strProgPath.empty())
100         {
101                 TCHAR temp[MAX_PATH] = {0};
102                 GetModuleFileName(NULL, temp, MAX_PATH);
103                 strProgPath = paths::GetPathOnly(temp);
104         }
105         return strProgPath;
106 }
107
108 /**
109  * @brief Get Windows directory.
110  * @return Windows directory.
111  */
112 String GetWindowsDirectory()
113 {
114         TCHAR path[MAX_PATH];
115         path[0] = _T('\0');
116         ::GetWindowsDirectory(path, MAX_PATH);
117         return path;
118 }
119
120 /**
121  * @brief Return User's My Documents Folder.
122  * This function returns full path to User's My Documents -folder.
123  * @return Full path to My Documents -folder.
124  */
125 String GetMyDocuments()
126 {
127         TCHAR path[MAX_PATH];
128         path[0] = _T('\0');
129         SHGetFolderPath(NULL, CSIDL_PERSONAL, NULL, 0, path);
130         return path;
131 }
132
133 /**
134  * @brief Return unique string for the instance.
135  * This function formats an unique string for WinMerge instance. The string
136  * is quaranteed to be unique for instance asking it.
137  * @param [in] name Additional name used as part of the string.
138  * @return Unique string for the instance.
139  */
140 String GetPerInstanceString(const String& name)
141 {
142         std::basic_stringstream<TCHAR> stream;
143         stream << name << Process::id();
144         return stream.str();
145 }
146
147 /**
148  * @brief Get system temporary directory.
149  * @return System temporary director.
150  */
151 String GetSystemTempPath()
152 {
153         try
154         {
155                 return ucr::toTString(Path::temp());
156         }
157         catch (...)
158         {
159                 return _T("");
160         }
161 }
162
163 static bool launchProgram(const String& sCmd, WORD wShowWindow)
164 {
165         STARTUPINFO stInfo = { sizeof(STARTUPINFO) };
166         stInfo.dwFlags = STARTF_USESHOWWINDOW;
167         stInfo.wShowWindow = wShowWindow;
168         PROCESS_INFORMATION processInfo;
169         bool retVal = !!CreateProcess(NULL, (LPTSTR)sCmd.c_str(),
170                 NULL, NULL, FALSE, CREATE_DEFAULT_ERROR_MODE, NULL, NULL,
171                 &stInfo, &processInfo);
172         if (!retVal)
173                 return false;
174         CloseHandle(processInfo.hThread);
175         CloseHandle(processInfo.hProcess);
176         return true;
177 }
178
179 /**
180  * @brief Load registry keys from .reg file if existing .reg file
181  */
182 bool LoadRegistryFromFile(const String& sRegFilePath)
183 {
184         if (paths::DoesPathExist(sRegFilePath) != paths::IS_EXISTING_FILE)
185                 return false;
186         return launchProgram(_T("reg.exe import \"") + sRegFilePath + _T("\""), SW_HIDE);
187 }
188
189 /** 
190  * @brief Save registry keys to .reg file if existing .reg file
191  */
192 bool SaveRegistryToFile(const String& sRegFilePath, const String& sRegDir)
193 {
194         if (paths::DoesPathExist(sRegFilePath) != paths::IS_EXISTING_FILE)
195                 return false;
196         DeleteFile(sRegFilePath.c_str());
197         return launchProgram(_T("reg.exe export HKCU\\") + sRegDir + _T(" \"") + sRegFilePath + _T("\""), SW_HIDE);
198 }
199
200 }