If longer than MAX_PATH, try to shorten it to reduce crash
[TortoiseGit.git] / src / Utils / CommonAppUtils.cpp
blob36970691123f031ca2cd8115f542963bdaa7067b
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, 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, CFormatMessageWrapper());
120 MessageBox(NULL, temp, _T("TortoiseGit"), MB_OK | MB_ICONINFORMATION);
122 return false;
125 if (bWaitForStartup)
127 WaitForInputIdle(process.hProcess, 10000);
130 CloseHandle(process.hThread);
131 CloseHandle(process.hProcess);
133 return true;
136 bool CCommonAppUtils::RunTortoiseGitProc(const CString& sCommandLine, bool uac, bool includeGroupingUUID)
138 CString pathToExecutable = CPathUtils::GetAppDirectory() + _T("TortoiseGitProc.exe");
139 CString sCmd;
140 sCmd.Format(_T("\"%s\" %s"), (LPCTSTR)pathToExecutable, (LPCTSTR)sCommandLine);
141 if (AfxGetMainWnd()->GetSafeHwnd() && (sCommandLine.Find(L"/hwnd:") < 0))
143 CString sCmdLine;
144 sCmdLine.Format(L"%s /hwnd:%ld", (LPCTSTR)sCommandLine, AfxGetMainWnd()->GetSafeHwnd());
145 sCmd.Format(_T("\"%s\" %s"), (LPCTSTR)pathToExecutable, (LPCTSTR)sCmdLine);
147 if (!g_sGroupingUUID.IsEmpty() && includeGroupingUUID)
149 sCmd += L" /groupuuid:\"";
150 sCmd += g_sGroupingUUID;
151 sCmd += L"\"";
154 return LaunchApplication(sCmd, NULL, false, NULL, uac);
157 bool CCommonAppUtils::IsAdminLogin()
159 SID_IDENTIFIER_AUTHORITY ntAuthority = SECURITY_NT_AUTHORITY;
160 PSID administratorsGroup;
161 // Initialize SID.
162 if (!AllocateAndInitializeSid(&ntAuthority, 2, SECURITY_BUILTIN_DOMAIN_RID, DOMAIN_ALIAS_RID_ADMINS, 0, 0, 0, 0, 0, 0, &administratorsGroup))
163 return false;
165 // Check whether the token is present in admin group.
166 BOOL isInAdminGroup = FALSE;
167 if (!CheckTokenMembership(NULL, administratorsGroup, &isInAdminGroup))
168 isInAdminGroup = FALSE;
170 // Free SID and return.
171 FreeSid(administratorsGroup);
172 return !!isInAdminGroup;
175 bool CCommonAppUtils::SetListCtrlBackgroundImage(HWND hListCtrl, UINT nID, int width /* = 128 */, int height /* = 128 */)
177 if ((((DWORD)CRegStdDWORD(_T("Software\\TortoiseGit\\ShowListBackgroundImage"), TRUE)) == FALSE))
178 return false;
179 ListView_SetTextBkColor(hListCtrl, CLR_NONE);
180 COLORREF bkColor = ListView_GetBkColor(hListCtrl);
181 // create a bitmap from the icon
182 HICON hIcon = (HICON)LoadImage(AfxGetResourceHandle(), MAKEINTRESOURCE(nID), IMAGE_ICON, width, height, LR_DEFAULTCOLOR);
183 if (!hIcon)
184 return false;
186 RECT rect = {0};
187 rect.right = width;
188 rect.bottom = height;
189 HBITMAP bmp = NULL;
191 HWND desktop = ::GetDesktopWindow();
192 if (desktop)
194 HDC screen_dev = ::GetDC(desktop);
195 if (screen_dev)
197 // Create a compatible DC
198 HDC dst_hdc = ::CreateCompatibleDC(screen_dev);
199 if (dst_hdc)
201 // Create a new bitmap of icon size
202 bmp = ::CreateCompatibleBitmap(screen_dev, rect.right, rect.bottom);
203 if (bmp)
205 // Select it into the compatible DC
206 HBITMAP old_dst_bmp = (HBITMAP)::SelectObject(dst_hdc, bmp);
207 // Fill the background of the compatible DC with the given color
208 ::SetBkColor(dst_hdc, bkColor);
209 ::ExtTextOut(dst_hdc, 0, 0, ETO_OPAQUE, &rect, NULL, 0, NULL);
211 // Draw the icon into the compatible DC
212 ::DrawIconEx(dst_hdc, 0, 0, hIcon, rect.right, rect.bottom, 0, NULL, DI_NORMAL);
213 ::SelectObject(dst_hdc, old_dst_bmp);
215 ::DeleteDC(dst_hdc);
218 ::ReleaseDC(desktop, screen_dev);
221 // Restore settings
222 DestroyIcon(hIcon);
224 if (bmp == NULL)
225 return false;
227 LVBKIMAGE lv;
228 lv.ulFlags = LVBKIF_TYPE_WATERMARK;
229 lv.hbm = bmp;
230 lv.xOffsetPercent = 100;
231 lv.yOffsetPercent = 100;
232 ListView_SetBkImage(hListCtrl, &lv);
233 return true;
236 bool CCommonAppUtils::FileOpenSave(CString& path, int * filterindex, UINT title, UINT filter, bool bOpen, HWND hwndOwner)
238 OPENFILENAME ofn = {0}; // common dialog box structure
239 TCHAR szFile[MAX_PATH] = {0}; // buffer for file name. Explorer can't handle paths longer than MAX_PATH.
240 ofn.lStructSize = sizeof(OPENFILENAME);
241 ofn.hwndOwner = hwndOwner;
242 if (path.GetLength() >= MAX_PATH)
244 CString dir = path;
245 while (true)
247 int index = dir.ReverseFind(_T('\\'));
248 if (index < 0)
249 break;
250 dir = dir.Left(index);
251 if (PathFileExists(dir))
252 break;
254 GetShortPathName(dir, szFile, MAX_PATH);
255 CString remain = path.Right(path.GetLength() - dir.GetLength());
256 _tcscat_s(szFile, MAX_PATH, remain);
258 else
259 _tcscpy_s(szFile, MAX_PATH, (LPCTSTR)path);
260 ofn.lpstrFile = szFile;
261 ofn.nMaxFile = _countof(szFile);
263 CSelectFileFilter fileFilter;
264 if (filter)
266 fileFilter.Load(filter);
267 ofn.lpstrFilter = fileFilter;
269 ofn.nFilterIndex = 1;
271 ofn.lpstrFileTitle = NULL;
272 ofn.nMaxFileTitle = 0;
273 ofn.lpstrInitialDir = NULL;
274 CString temp;
275 if (title)
277 temp.LoadString(title);
278 CStringUtils::RemoveAccelerators(temp);
280 ofn.lpstrTitle = temp;
281 if (bOpen)
282 ofn.Flags = OFN_PATHMUSTEXIST | OFN_FILEMUSTEXIST | OFN_HIDEREADONLY | OFN_EXPLORER;
283 else
284 ofn.Flags = OFN_OVERWRITEPROMPT | OFN_EXPLORER;
287 // Display the Open dialog box.
288 bool bRet = false;
289 if (bOpen)
291 bRet = !!GetOpenFileName(&ofn);
293 else
295 bRet = !!GetSaveFileName(&ofn);
297 SetCurrentDirectory(sOrigCWD.GetBuffer());
298 sOrigCWD.ReleaseBuffer();
299 if (bRet)
301 path = CString(ofn.lpstrFile);
302 if (filterindex)
303 *filterindex = ofn.nFilterIndex;
304 return true;
306 return false;
309 void CCommonAppUtils::SetCharFormat(CWnd* window, DWORD mask , DWORD effects, const std::vector<CHARRANGE>& positions)
311 CHARFORMAT2 format;
312 SecureZeroMemory(&format, sizeof(CHARFORMAT2));
313 format.cbSize = sizeof(CHARFORMAT2);
314 format.dwMask = mask;
315 format.dwEffects = effects;
316 format.crTextColor = effects;
318 for (std::vector<CHARRANGE>::const_iterator iter = positions.begin(), end = positions.end(); iter != end; ++iter)
320 CHARRANGE range = *iter;
321 window->SendMessage(EM_EXSETSEL, NULL, (LPARAM)&range);
322 window->SendMessage(EM_SETCHARFORMAT, SCF_SELECTION, (LPARAM)&format);
326 void CCommonAppUtils::SetCharFormat(CWnd* window, DWORD mask, DWORD effects )
328 CHARFORMAT2 format;
329 SecureZeroMemory(&format, sizeof(CHARFORMAT2));
330 format.cbSize = sizeof(CHARFORMAT2);
331 format.dwMask = mask;
332 format.dwEffects = effects;
333 window->SendMessage(EM_SETCHARFORMAT, SCF_SELECTION, (LPARAM)&format);