Navigate selection history via log jump up/down button
[TortoiseGit.git] / src / Utils / CommonAppUtils.cpp
blobf8a5abcced311389dcb05f6cc12653f39e36fb91
1 // TortoiseGit - a Windows shell extension for easy version control
3 // Copyright (C) 2008-2013 - TortoiseGit
4 // Copyright (C) 2003-2008,2010 - TortoiseSVN
6 // This program is free software; you can redistribute it and/or
7 // modify it under the terms of the GNU General Public License
8 // as published by the Free Software Foundation; either version 2
9 // of the License, or (at your option) any later version.
11 // This program is distributed in the hope that it will be useful,
12 // but WITHOUT ANY WARRANTY; without even the implied warranty of
13 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 // GNU General Public License for more details.
16 // You should have received a copy of the GNU General Public License
17 // along with this program; if not, write to the Free Software Foundation,
18 // 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
20 #include "stdafx.h"
21 #include "..\Resources\LoglistCommonResource.h"
22 #include "CommonAppUtils.h"
23 #include "PathUtils.h"
24 #include "StringUtils.h"
25 #include "CreateProcessHelper.h"
26 #include "FormatMessageWrapper.h"
27 #include "registry.h"
28 #include "SelectFileFilter.h"
30 extern CString sOrigCWD;
31 extern CString g_sGroupingUUID;
33 bool CCommonAppUtils::LaunchApplication(const CString& sCommandLine, UINT idErrMessageFormat, bool bWaitForStartup, CString *cwd, bool uac)
35 CString theCWD = sOrigCWD;
36 if (cwd != NULL)
37 theCWD = *cwd;
39 if (uac)
41 CString file, param;
42 SHELLEXECUTEINFO shellinfo;
43 memset(&shellinfo, 0, sizeof(shellinfo));
44 shellinfo.cbSize = sizeof(shellinfo);
45 shellinfo.hwnd = NULL;
46 shellinfo.lpVerb = _T("runas");
47 shellinfo.nShow = SW_SHOWNORMAL;
48 shellinfo.fMask = SEE_MASK_NOCLOSEPROCESS;
49 shellinfo.lpDirectory = theCWD;
51 int pos = sCommandLine.Find('"');
52 if (pos == 0)
54 pos = sCommandLine.Find('"', 2);
55 if (pos > 1)
57 file = sCommandLine.Mid(1, pos - 1);
58 param = sCommandLine.Mid(pos + 1);
60 else
62 if (idErrMessageFormat != 0)
64 CString temp;
65 temp.Format(idErrMessageFormat, CFormatMessageWrapper());
66 MessageBox(NULL, temp, _T("TortoiseGit"), MB_OK | MB_ICONINFORMATION);
68 return false;
71 else
73 pos = sCommandLine.Find(' ', 1);
74 if (pos > 0)
76 file = sCommandLine.Mid(0, pos);
77 param = sCommandLine.Mid(pos + 1);
79 else
80 file = sCommandLine;
83 shellinfo.lpFile = file;
84 shellinfo.lpParameters = param;
86 if (!ShellExecuteEx(&shellinfo))
88 if (idErrMessageFormat != 0)
90 CString temp;
91 temp.Format(idErrMessageFormat, (CString)CFormatMessageWrapper());
92 MessageBox(NULL, temp, _T("TortoiseGit"), MB_OK | MB_ICONINFORMATION);
94 return false;
97 if (bWaitForStartup)
99 WaitForInputIdle(shellinfo.hProcess, 10000);
102 CloseHandle(shellinfo.hProcess);
104 else
106 STARTUPINFO startup;
107 PROCESS_INFORMATION process;
108 memset(&startup, 0, sizeof(startup));
109 startup.cb = sizeof(startup);
110 memset(&process, 0, sizeof(process));
112 CString cleanCommandLine(sCommandLine);
114 if (CreateProcess(NULL, const_cast<TCHAR*>((LPCTSTR)cleanCommandLine), NULL, NULL, FALSE, 0, 0, theCWD, &startup, &process)==0)
116 if(idErrMessageFormat != 0)
118 CString temp;
119 temp.Format(idErrMessageFormat, (CString)CFormatMessageWrapper());
120 MessageBox(NULL, temp, _T("TortoiseGit"), MB_OK | MB_ICONINFORMATION);
122 return false;
125 AllowSetForegroundWindow(process.dwProcessId);
127 if (bWaitForStartup)
129 WaitForInputIdle(process.hProcess, 10000);
132 CloseHandle(process.hThread);
133 CloseHandle(process.hProcess);
135 return true;
138 bool CCommonAppUtils::RunTortoiseGitProc(const CString& sCommandLine, bool uac, bool includeGroupingUUID)
140 CString pathToExecutable = CPathUtils::GetAppDirectory() + _T("TortoiseGitProc.exe");
141 CString sCmd;
142 sCmd.Format(_T("\"%s\" %s"), (LPCTSTR)pathToExecutable, (LPCTSTR)sCommandLine);
143 if (AfxGetMainWnd()->GetSafeHwnd() && (sCommandLine.Find(L"/hwnd:") < 0))
145 CString sCmdLine;
146 sCmdLine.Format(L"%s /hwnd:%p", (LPCTSTR)sCommandLine, (void*)AfxGetMainWnd()->GetSafeHwnd());
147 sCmd.Format(_T("\"%s\" %s"), (LPCTSTR)pathToExecutable, (LPCTSTR)sCmdLine);
149 if (!g_sGroupingUUID.IsEmpty() && includeGroupingUUID)
151 sCmd += L" /groupuuid:\"";
152 sCmd += g_sGroupingUUID;
153 sCmd += L"\"";
156 return LaunchApplication(sCmd, NULL, false, NULL, uac);
159 bool CCommonAppUtils::IsAdminLogin()
161 SID_IDENTIFIER_AUTHORITY ntAuthority = SECURITY_NT_AUTHORITY;
162 PSID administratorsGroup;
163 // Initialize SID.
164 if (!AllocateAndInitializeSid(&ntAuthority, 2, SECURITY_BUILTIN_DOMAIN_RID, DOMAIN_ALIAS_RID_ADMINS, 0, 0, 0, 0, 0, 0, &administratorsGroup))
165 return false;
167 // Check whether the token is present in admin group.
168 BOOL isInAdminGroup = FALSE;
169 if (!CheckTokenMembership(NULL, administratorsGroup, &isInAdminGroup))
170 isInAdminGroup = FALSE;
172 // Free SID and return.
173 FreeSid(administratorsGroup);
174 return !!isInAdminGroup;
177 bool CCommonAppUtils::SetListCtrlBackgroundImage(HWND hListCtrl, UINT nID, int width /* = 128 */, int height /* = 128 */)
179 if ((((DWORD)CRegStdDWORD(_T("Software\\TortoiseGit\\ShowListBackgroundImage"), TRUE)) == FALSE))
180 return false;
181 ListView_SetTextBkColor(hListCtrl, CLR_NONE);
182 COLORREF bkColor = ListView_GetBkColor(hListCtrl);
183 // create a bitmap from the icon
184 HICON hIcon = (HICON)LoadImage(AfxGetResourceHandle(), MAKEINTRESOURCE(nID), IMAGE_ICON, width, height, LR_DEFAULTCOLOR);
185 if (!hIcon)
186 return false;
188 RECT rect = {0};
189 rect.right = width;
190 rect.bottom = height;
191 HBITMAP bmp = NULL;
193 HWND desktop = ::GetDesktopWindow();
194 if (desktop)
196 HDC screen_dev = ::GetDC(desktop);
197 if (screen_dev)
199 // Create a compatible DC
200 HDC dst_hdc = ::CreateCompatibleDC(screen_dev);
201 if (dst_hdc)
203 // Create a new bitmap of icon size
204 bmp = ::CreateCompatibleBitmap(screen_dev, rect.right, rect.bottom);
205 if (bmp)
207 // Select it into the compatible DC
208 HBITMAP old_dst_bmp = (HBITMAP)::SelectObject(dst_hdc, bmp);
209 // Fill the background of the compatible DC with the given color
210 ::SetBkColor(dst_hdc, bkColor);
211 ::ExtTextOut(dst_hdc, 0, 0, ETO_OPAQUE, &rect, NULL, 0, NULL);
213 // Draw the icon into the compatible DC
214 ::DrawIconEx(dst_hdc, 0, 0, hIcon, rect.right, rect.bottom, 0, NULL, DI_NORMAL);
215 ::SelectObject(dst_hdc, old_dst_bmp);
217 ::DeleteDC(dst_hdc);
219 ::ReleaseDC(desktop, screen_dev);
223 // Restore settings
224 DestroyIcon(hIcon);
226 if (bmp == NULL)
227 return false;
229 LVBKIMAGE lv;
230 lv.ulFlags = LVBKIF_TYPE_WATERMARK;
231 lv.hbm = bmp;
232 lv.xOffsetPercent = 100;
233 lv.yOffsetPercent = 100;
234 ListView_SetBkImage(hListCtrl, &lv);
235 return true;
238 bool CCommonAppUtils::FileOpenSave(CString& path, int * filterindex, UINT title, UINT filter, bool bOpen, HWND hwndOwner, LPCTSTR defaultExt)
240 OPENFILENAME ofn = {0}; // common dialog box structure
241 TCHAR szFile[MAX_PATH] = {0}; // buffer for file name. Explorer can't handle paths longer than MAX_PATH.
242 ofn.lStructSize = sizeof(OPENFILENAME);
243 ofn.hwndOwner = hwndOwner;
244 if (path.GetLength() >= MAX_PATH)
246 CString dir = path;
247 while (true)
249 int index = dir.ReverseFind(_T('\\'));
250 if (index < 0)
251 break;
252 dir = dir.Left(index);
253 if (PathFileExists(dir))
254 break;
256 GetShortPathName(dir, szFile, MAX_PATH);
257 CString remain = path.Right(path.GetLength() - dir.GetLength());
258 _tcscat_s(szFile, MAX_PATH, remain);
260 else
261 _tcscpy_s(szFile, MAX_PATH, (LPCTSTR)path);
262 ofn.lpstrFile = szFile;
263 ofn.nMaxFile = _countof(szFile);
265 CSelectFileFilter fileFilter;
266 if (filter)
268 fileFilter.Load(filter);
269 ofn.lpstrFilter = fileFilter;
271 ofn.nFilterIndex = 1;
273 ofn.lpstrFileTitle = NULL;
274 ofn.nMaxFileTitle = 0;
275 ofn.lpstrInitialDir = NULL;
276 ofn.lpstrDefExt = defaultExt;
277 CString temp;
278 if (title)
280 temp.LoadString(title);
281 CStringUtils::RemoveAccelerators(temp);
283 ofn.lpstrTitle = temp;
284 if (bOpen)
285 ofn.Flags = OFN_PATHMUSTEXIST | OFN_FILEMUSTEXIST | OFN_HIDEREADONLY | OFN_EXPLORER;
286 else
287 ofn.Flags = OFN_OVERWRITEPROMPT | OFN_EXPLORER;
290 // Display the Open dialog box.
291 bool bRet = false;
292 if (bOpen)
294 bRet = !!GetOpenFileName(&ofn);
296 else
298 bRet = !!GetSaveFileName(&ofn);
300 SetCurrentDirectory(sOrigCWD.GetBuffer());
301 sOrigCWD.ReleaseBuffer();
302 if (bRet)
304 path = CString(ofn.lpstrFile);
305 if (filterindex)
306 *filterindex = ofn.nFilterIndex;
307 return true;
309 return false;
312 void CCommonAppUtils::SetCharFormat(CWnd* window, DWORD mask , DWORD effects, const std::vector<CHARRANGE>& positions)
314 CHARFORMAT2 format;
315 SecureZeroMemory(&format, sizeof(CHARFORMAT2));
316 format.cbSize = sizeof(CHARFORMAT2);
317 format.dwMask = mask;
318 format.dwEffects = effects;
319 format.crTextColor = effects;
321 for (std::vector<CHARRANGE>::const_iterator iter = positions.begin(), end = positions.end(); iter != end; ++iter)
323 CHARRANGE range = *iter;
324 window->SendMessage(EM_EXSETSEL, NULL, (LPARAM)&range);
325 window->SendMessage(EM_SETCHARFORMAT, SCF_SELECTION, (LPARAM)&format);
329 void CCommonAppUtils::SetCharFormat(CWnd* window, DWORD mask, DWORD effects )
331 CHARFORMAT2 format;
332 SecureZeroMemory(&format, sizeof(CHARFORMAT2));
333 format.cbSize = sizeof(CHARFORMAT2);
334 format.dwMask = mask;
335 format.dwEffects = effects;
336 window->SendMessage(EM_SETCHARFORMAT, SCF_SELECTION, (LPARAM)&format);