1 // TortoiseGit - a Windows shell extension for easy version control
3 // Copyright (C) 2008-2016 - TortoiseGit
4 // Copyright (C) 2003-2008, 2012-2014 - 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.
21 #include "TortoiseProc.h"
22 #include "SysImageList.h"
23 #include "..\Utils\CrashReport.h"
24 #include "CmdLineParser.h"
27 #include "PathUtils.h"
28 #include "StringUtils.h"
29 #include "UnicodeUtils.h"
30 #include "MessageBox.h"
31 #include "DirFileEnum.h"
32 #include "GitAdminDir.h"
34 #include "SmartHandle.h"
35 #include "Commands\Command.h"
36 #include "..\version.h"
37 #include "JumpListHelpers.h"
38 #include "SinglePropSheetDlg.h"
39 #include "Settings\setmainpage.h"
40 #include "ConfigureGitExe.h"
41 #include "Libraries.h"
42 #include "TaskbarUUID.h"
43 #include "ProjectProperties.h"
44 #include "HistoryCombo.h"
49 #include "WindowsCredentialsStore.h"
51 #define STRUCT_IOVEC_DEFINED
57 #pragma comment(linker, "\"/manifestdependency:type='win32' name='Microsoft.Windows.Common-Controls' version='6.0.0.0' processorArchitecture='*' publicKeyToken='6595b64144ccf1df' language='*'\"")
59 BEGIN_MESSAGE_MAP(CTortoiseProcApp
, CWinAppEx
)
60 ON_COMMAND(ID_HELP
, CWinAppEx::OnHelp
)
63 //////////////////////////////////////////////////////////////////////////
65 CTortoiseProcApp::CTortoiseProcApp()
67 CTraceToOutputDebugString::Instance()(_T(__FUNCTION__
) L
": Constructor\n");
69 CCrashReport::Instance().AddUserInfoToReport(L
"CommandLine", GetCommandLine());
73 CGit::SetGit2CredentialCallback(CAppUtils::Git2GetUserPassword
);
74 CGit::SetGit2CertificateCheckCertificate(CAppUtils::Git2CertificateCheck
);
75 m_bLoadUserToolbars
= FALSE
;
78 m_gdiplusToken
= NULL
;
79 #if defined (_WIN64) && _MSC_VER == 1800
84 CTortoiseProcApp::~CTortoiseProcApp()
87 git_libgit2_shutdown();
90 // The one and only CTortoiseProcApp object
91 CTortoiseProcApp theApp
;
93 CString g_sGroupingUUID
;
94 CString g_sGroupingIcon
;
95 bool g_bGroupingRemoveIcon
= false;
97 CGitIndexFileMap g_IndexFileMap
;
99 #if ENABLE_CRASHHANLDER
100 CCrashReportTGit
crasher(L
"TortoiseGit " _T(APP_X64_STRING
), TGIT_VERMAJOR
, TGIT_VERMINOR
, TGIT_VERMICRO
, TGIT_VERBUILD
, TGIT_VERDATE
);
103 // CTortoiseProcApp initialization
105 BOOL
CTortoiseProcApp::InitInstance()
107 CTraceToOutputDebugString::Instance()(_T(__FUNCTION__
) L
": InitInstance\n");
109 CMFCVisualManager::SetDefaultManager(RUNTIME_CLASS(CMFCVisualManagerWindows
));
110 CMFCButton::EnableWindowsTheming();
112 Gdiplus::GdiplusStartupInput gdiplusStartupInput
;
113 Gdiplus::GdiplusStartup(&m_gdiplusToken
, &gdiplusStartupInput
, nullptr);
115 //set the resource dll for the required language
116 CRegDWORD loc
= CRegDWORD(L
"Software\\TortoiseGit\\LanguageID", 1033);
119 CStringA langpath
= CStringA(CPathUtils::GetAppParentDirectory());
120 langpath
+= "Languages";
123 langDll
.Format(L
"%sLanguages\\TortoiseProc%ld.dll", (LPCTSTR
)CPathUtils::GetAppParentDirectory(), langId
);
125 CString sVer
= _T(STRPRODUCTVER
);
126 CString sFileVer
= CPathUtils::GetVersionFromFile(langDll
);
127 if (sFileVer
== sVer
)
129 HINSTANCE hInst
= LoadLibrary(langDll
);
132 CTraceToOutputDebugString::Instance()(_T(__FUNCTION__
) L
": Load Language DLL %s\n", langDll
);
133 AfxSetResourceHandle(hInst
);
138 DWORD lid
= SUBLANGID(langId
);
141 langId
= MAKELANGID(PRIMARYLANGID(langId
), lid
);
145 } while (langId
!= 0);
148 langStr
.Format(L
"%ld", langId
);
149 CCrashReport::Instance().AddUserInfoToReport(L
"LanguageID", langStr
);
151 TCHAR buf
[6] = { 0 };
152 wcscpy_s(buf
, L
"en");
154 // MFC uses a help file with the same name as the application by default,
155 // which means we have to change that default to our language specific help files
156 CString sHelppath
= CPathUtils::GetAppDirectory() + L
"TortoiseGit_en.chm";
157 free((void*)m_pszHelpFilePath
);
158 m_pszHelpFilePath
=_wcsdup(sHelppath
);
159 sHelppath
= CPathUtils::GetAppParentDirectory() + L
"Languages\\TortoiseGit_en.chm";
162 CString sLang
= L
"_";
163 if (GetLocaleInfo(MAKELCID(langId
, SORT_DEFAULT
), LOCALE_SISO639LANGNAME
, buf
, _countof(buf
)))
166 sHelppath
.Replace(L
"_en", sLang
);
167 if (PathFileExists(sHelppath
))
169 free((void*)m_pszHelpFilePath
);
170 m_pszHelpFilePath
=_wcsdup(sHelppath
);
174 sHelppath
.Replace(sLang
, L
"_en");
175 if (GetLocaleInfo(MAKELCID(langId
, SORT_DEFAULT
), LOCALE_SISO3166CTRYNAME
, buf
, _countof(buf
)))
179 sHelppath
.Replace(L
"_en", sLang
);
180 if (PathFileExists(sHelppath
))
182 free((void*)m_pszHelpFilePath
);
183 m_pszHelpFilePath
=_wcsdup(sHelppath
);
187 sHelppath
.Replace(sLang
, L
"_en");
189 DWORD lid
= SUBLANGID(langId
);
192 langId
= MAKELANGID(PRIMARYLANGID(langId
), lid
);
196 CTraceToOutputDebugString::Instance()(_T(__FUNCTION__
) L
": Set Help Filename %s\n", m_pszHelpFilePath
);
197 setlocale(LC_ALL
, "");
199 if (!g_Git
.CheckMsysGitDir())
201 UINT ret
= CMessageBox::Show(nullptr, IDS_PROC_NOMSYSGIT
, IDS_APPNAME
, 3, IDI_HAND
, IDS_PROC_SETMSYSGITPATH
, IDS_PROC_GOTOMSYSGITWEBSITE
, IDS_ABORTBUTTON
);
204 ShellExecute(nullptr, L
"open", GIT_FOR_WINDOWS_URL
, nullptr, nullptr, SW_SHOW
);
208 // open settings dialog
209 CSinglePropSheetDlg(CString(MAKEINTRESOURCE(IDS_PROC_SETTINGS_TITLE
)), new CSetMainPage(), this->GetMainWnd()).DoModal();
213 if (!CConfigureGitExe::CheckGitVersion(hWndExplorer
))
217 CTraceToOutputDebugString::Instance()(_T(__FUNCTION__
) L
": Registering Crash Report ...\n");
218 CCrashReport::Instance().AddUserInfoToReport(L
"msysGitDir", CGit::ms_LastMsysGitDir
);
219 CString versionString
;
220 versionString
.Format(L
"%X", CGit::ms_LastMsysGitVersion
);
221 CCrashReport::Instance().AddUserInfoToReport(L
"msysGitVersion", versionString
);
224 CTraceToOutputDebugString::Instance()(_T(__FUNCTION__
) L
": Initializing UI components ...\n");
225 // InitCommonControls() is required on Windows XP if an application
226 // manifest specifies use of ComCtl32.dll version 6 or later to enable
227 // visual styles. Otherwise, any window creation will fail.
229 INITCOMMONCONTROLSEX used
= {
230 sizeof(INITCOMMONCONTROLSEX
),
231 ICC_ANIMATE_CLASS
| ICC_BAR_CLASSES
| ICC_COOL_CLASSES
| ICC_DATE_CLASSES
|
232 ICC_HOTKEY_CLASS
| ICC_INTERNET_CLASSES
| ICC_LISTVIEW_CLASSES
|
233 ICC_NATIVEFNTCTL_CLASS
| ICC_PAGESCROLLER_CLASS
| ICC_PROGRESS_CLASS
|
234 ICC_TAB_CLASSES
| ICC_TREEVIEW_CLASSES
| ICC_UPDOWN_CLASS
|
235 ICC_USEREX_CLASSES
| ICC_WIN95_CLASSES
237 InitCommonControlsEx(&used
);
239 AfxEnableControlContainer();
241 CWinAppEx::InitInstance();
242 SetRegistryKey(L
"TortoiseGit");
244 CHistoryCombo::m_nGitIconIndex
= SYS_IMAGE_LIST().AddIcon((HICON
)LoadImage(AfxGetResourceHandle(), MAKEINTRESOURCE(IDI_GITCONFIG
), IMAGE_ICON
, 0, 0, LR_DEFAULTSIZE
));
245 AfxGetApp()->m_pszProfileName
= _wcsdup(L
"TortoiseProc"); // w/o this ResizableLib will store data under TortoiseGitProc which is not compatible with older versions
247 CCmdLineParser
parser(AfxGetApp()->m_lpCmdLine
);
249 hWndExplorer
= nullptr;
250 CString sVal
= parser
.GetVal(L
"hwnd");
252 hWndExplorer
= (HWND
)_wcstoui64(sVal
, nullptr, 16);
254 while (GetParent(hWndExplorer
))
255 hWndExplorer
= GetParent(hWndExplorer
);
256 if (!IsWindow(hWndExplorer
))
257 hWndExplorer
= nullptr;
259 // if HKCU\Software\TortoiseGit\Debug is not 0, show our command line
261 if (CRegDWORD(L
"Software\\TortoiseGit\\Debug", FALSE
) == TRUE
)
262 AfxMessageBox(AfxGetApp()->m_lpCmdLine
, MB_OK
| MB_ICONINFORMATION
);
264 if (parser
.HasKey(L
"urlhandler"))
266 CString url
= parser
.GetVal(L
"urlhandler");
267 if (CStringUtils::StartsWith(url
, L
"tgit://clone/"))
268 url
= url
.Mid(13); // 21 = "tgit://clone/".GetLength()
269 else if (CStringUtils::StartsWith(url
, L
"github-windows://openRepo/"))
271 url
= url
.Mid(26); // 26 = "github-windows://openRepo/".GetLength()
272 int questioMark
= url
.Find('?');
274 url
= url
.Left(questioMark
);
276 else if (CStringUtils::StartsWith(url
, L
"smartgit://cloneRepo/"))
277 url
= url
.Mid(21); // 21 = "smartgit://cloneRepo/".GetLength()
280 CMessageBox::Show(nullptr, IDS_ERR_INVALIDPATH
, IDS_APPNAME
, MB_ICONERROR
);
284 newCmd
.Format(L
"/command:clone /url:\"%s\" /hasurlhandler", (LPCTSTR
)url
);
285 parser
= CCmdLineParser(newCmd
);
288 if (parser
.HasKey(L
"path") && parser
.HasKey(L
"pathfile"))
290 CMessageBox::Show(nullptr, IDS_ERR_INVALIDPATH
, IDS_APPNAME
, MB_ICONERROR
);
294 CTGitPath cmdLinePath
;
295 CTGitPathList pathList
;
296 if (g_sGroupingUUID
.IsEmpty())
297 g_sGroupingUUID
= parser
.GetVal(L
"groupuuid");
298 if (parser
.HasKey(L
"pathfile"))
300 CString sPathfileArgument
= CPathUtils::GetLongPathname(parser
.GetVal(L
"pathfile"));
302 cmdLinePath
.SetFromUnknown(sPathfileArgument
);
303 if (pathList
.LoadFromFile(cmdLinePath
)==false)
304 return FALSE
; // no path specified!
305 if (parser
.HasKey(L
"deletepathfile"))
307 // We can delete the temporary path file, now that we've loaded it
308 ::DeleteFile(cmdLinePath
.GetWinPath());
310 // This was a path to a temporary file - it's got no meaning now, and
311 // anybody who uses it again is in for a problem...
317 CString sPathArgument
= CPathUtils::GetLongPathname(parser
.GetVal(L
"path"));
318 if (parser
.HasKey(L
"expaths"))
320 // an /expaths param means we're started via the buttons in our Win7 library
321 // and that means the value of /expaths is the current directory, and
322 // the selected paths are then added as additional parameters but without a key, only a value
324 // because of the "strange treatment of quotation marks and backslashes by CommandLineToArgvW"
325 // we have to escape the backslashes first. Since we're only dealing with paths here, that's
327 // Without this, a command line like:
328 // /command:commit /expaths:"D:\" "D:\Utils"
329 // would fail because the "D:\" is treated as the backslash being the escape char for the quotation
330 // mark and we'd end up with:
331 // argv[1] = /command:commit
332 // argv[2] = /expaths:D:" D:\Utils
333 // See here for more details: http://blogs.msdn.com/b/oldnewthing/archive/2010/09/17/10063629.aspx
334 CString cmdLine
= GetCommandLineW();
335 cmdLine
.Replace(L
"\\", L
"\\\\");
337 LPWSTR
*szArglist
= CommandLineToArgvW(cmdLine
, &nArgs
);
340 // argument 0 is the process path, so start with 1
341 for (int i
= 1; i
< nArgs
; ++i
)
343 if (szArglist
[i
][0] != '/')
345 if (!sPathArgument
.IsEmpty())
346 sPathArgument
+= '*';
347 sPathArgument
+= szArglist
[i
];
350 sPathArgument
.Replace(L
"\\\\", L
"\\");
352 LocalFree(szArglist
);
354 if (sPathArgument
.IsEmpty() && parser
.HasKey(L
"path"))
356 CMessageBox::Show(hWndExplorer
, IDS_ERR_INVALIDPATH
, IDS_APPNAME
, MB_ICONERROR
);
359 int asterisk
= sPathArgument
.Find('*');
360 cmdLinePath
.SetFromUnknown(asterisk
>= 0 ? sPathArgument
.Left(asterisk
) : sPathArgument
);
361 pathList
.LoadFromAsteriskSeparatedString(sPathArgument
);
364 if (pathList
.IsEmpty()) {
365 pathList
.AddPath(CTGitPath::CTGitPath(g_Git
.m_CurrentDir
));
368 // Set CWD to temporary dir, and restore it later
370 DWORD len
= GetCurrentDirectory(0, nullptr);
373 auto originalCurrentDirectory
= std::make_unique
<TCHAR
[]>(len
);
374 if (GetCurrentDirectory(len
, originalCurrentDirectory
.get()))
376 sOrigCWD
= originalCurrentDirectory
.get();
377 sOrigCWD
= CPathUtils::GetLongPathname(sOrigCWD
);
380 TCHAR pathbuf
[MAX_PATH
] = {0};
381 GetTortoiseGitTempPath(MAX_PATH
, pathbuf
);
382 SetCurrentDirectory(pathbuf
);
385 CheckForNewerVersion();
387 CAutoGeneralHandle TGitMutex
= ::CreateMutex(nullptr, FALSE
, L
"TortoiseGitProc.exe");
388 if (!g_Git
.SetCurrentDir(cmdLinePath
.GetWinPathString(), parser
.HasKey(L
"submodule") == TRUE
))
390 for (int i
= 0; i
< pathList
.GetCount(); ++i
)
391 if(g_Git
.SetCurrentDir(pathList
[i
].GetWinPath()))
394 if (parser
.HasKey(L
"pathfile") && parser
.HasKey(L
"submodule"))
395 g_Git
.SetCurrentDir(pathList
[0].GetWinPathString(), true);
397 if(!g_Git
.m_CurrentDir
.IsEmpty())
399 sOrigCWD
= g_Git
.m_CurrentDir
;
400 SetCurrentDirectory(g_Git
.m_CurrentDir
);
403 if (g_sGroupingUUID
.IsEmpty())
405 CRegStdDWORD groupSetting
= CRegStdDWORD(L
"Software\\TortoiseGit\\GroupTaskbarIconsPerRepo", 3);
406 switch (DWORD(groupSetting
))
410 // implemented differently to TortoiseSVN atm
416 if (GitAdminDir::HasAdminDir(g_Git
.m_CurrentDir
, true, &wcroot
))
419 CStringA
wcRootA(wcroot
+ CPathUtils::GetAppDirectory());
420 if (!git_odb_hash(&oid
, wcRootA
.MakeLower(), wcRootA
.GetLength(), GIT_OBJ_BLOB
))
423 git_oid_tostr(hash
.GetBufferSetLength(GIT_OID_HEXSZ
+ 1), GIT_OID_HEXSZ
+ 1, &oid
);
424 hash
.ReleaseBuffer();
425 g_sGroupingUUID
= hash
;
427 ProjectProperties pp
;
429 CString icon
= pp
.sIcon
;
430 icon
.Replace('/', '\\');
432 g_bGroupingRemoveIcon
= true;
433 g_sGroupingIcon
= icon
;
439 CString sAppID
= GetTaskIDPerUUID(g_sGroupingUUID
).c_str();
440 InitializeJumpList(sAppID
);
441 EnsureGitLibrary(false);
447 // requires CWD to be set
448 CGit::m_LogEncode
= CAppUtils::GetLogOutputEncode();
450 // make sure all config files are read in order to check that none contains an error
451 g_Git
.GetConfigValue(L
"doesnot.exist");
460 UINT choice
= CMessageBox::Show(hWndExplorer
, err
, L
"TortoiseGit", 1, IDI_ERROR
, CString(MAKEINTRESOURCE(IDS_PROC_EDITLOCALGITCONFIG
)), CString(MAKEINTRESOURCE(IDS_PROC_EDITGLOBALGITCONFIG
)), CString(MAKEINTRESOURCE(IDS_ABORTBUTTON
)));
463 // open the config file with alternative editor
464 CAppUtils::LaunchAlternativeEditor(g_Git
.GetGitLocalConfig());
466 else if (choice
== 2)
468 // open the global config file with alternative editor
469 CAppUtils::LaunchAlternativeEditor(g_Git
.GetGitGlobalConfig());
475 // execute the requested command
476 CommandServer server
;
477 Command
* cmd
= server
.GetCommand(parser
.GetVal(L
"command"));
480 cmd
->SetExplorerHwnd(hWndExplorer
);
482 cmd
->SetParser(parser
);
483 cmd
->SetPaths(pathList
, cmdLinePath
);
485 retSuccess
= cmd
->Execute();
489 // Look for temporary files left around by TortoiseSVN and
490 // remove them. But only delete 'old' files because some
491 // apps might still be needing the recent ones.
493 DWORD len
= GetTortoiseGitTempPath(0, nullptr);
494 auto path
= std::make_unique
<TCHAR
[]>(len
+ 100);
495 len
= GetTortoiseGitTempPath (len
+ 100, path
.get());
498 CDirFileEnum
finder(path
.get());
500 ::GetSystemTimeAsFileTime(&systime_
);
501 __int64 systime
= (((_int64
)systime_
.dwHighDateTime
)<<32) | ((__int64
)systime_
.dwLowDateTime
);
504 while (finder
.NextFile(filepath
, &isDir
))
506 HANDLE hFile
= ::CreateFile(filepath
, GENERIC_READ
, FILE_SHARE_READ
, nullptr, OPEN_EXISTING
, isDir
? FILE_FLAG_BACKUP_SEMANTICS
: 0, nullptr);
507 if (hFile
!= INVALID_HANDLE_VALUE
)
509 FILETIME createtime_
;
510 if (::GetFileTime(hFile
, &createtime_
, nullptr, nullptr))
512 ::CloseHandle(hFile
);
513 __int64 createtime
= (((_int64
)createtime_
.dwHighDateTime
)<<32) | ((__int64
)createtime_
.dwLowDateTime
);
514 if ((createtime
+ 864000000000) < systime
) //only delete files older than a day
516 ::SetFileAttributes(filepath
, FILE_ATTRIBUTE_NORMAL
);
518 ::RemoveDirectory(filepath
);
520 ::DeleteFile(filepath
);
524 ::CloseHandle(hFile
);
530 // Since the dialog has been closed, return FALSE so that we exit the
531 // application, rather than start the application's message pump.
535 void CTortoiseProcApp::CheckUpgrade()
537 CRegString regVersion
= CRegString(L
"Software\\TortoiseGit\\CurrentVersion");
538 CString sVersion
= regVersion
;
539 CTraceToOutputDebugString::Instance()(_T(__FUNCTION__
) L
": Current TGit Version %s\n", (LPCTSTR
)sVersion
);
540 if (sVersion
.Compare(_T(STRPRODUCTVER
))==0)
542 // we're starting the first time with a new version!
545 int pos
= sVersion
.Find('.');
548 lVersion
= (_wtol(sVersion
.Left(pos
)) << 24);
549 lVersion
|= (_wtol(sVersion
.Mid(pos
+ 1)) << 16);
550 pos
= sVersion
.Find('.', pos
+1);
551 lVersion
|= (_wtol(sVersion
.Mid(pos
+ 1)) << 8);
555 pos
= sVersion
.Find(',');
558 lVersion
= (_wtol(sVersion
.Left(pos
)) << 24);
559 lVersion
|= (_wtol(sVersion
.Mid(pos
+ 1)) << 16);
560 pos
= sVersion
.Find(',', pos
+1);
561 lVersion
|= (_wtol(sVersion
.Mid(pos
+ 1)) << 8);
566 if (CRegStdDWORD(L
"Software\\TortoiseGit\\UseLibgit2", TRUE
) != TRUE
)
568 if (CMessageBox::Show(nullptr, L
"You have disabled the usage of libgit2 in TortoiseGit.\n\nThis might be the case in order to resolve an issue in an older TortoiseGit version.\n\nDo you want to restore the default value (i.e., enable it)?", L
"TortoiseGit", MB_ICONQUESTION
| MB_YESNO
) == IDYES
)
569 CRegStdDWORD(L
"Software\\TortoiseGit\\UseLibgit2").removeValue();
572 if (CRegStdDWORD(L
"Software\\TortoiseGit\\UseLibgit2_mask").exists())
574 if (CMessageBox::Show(nullptr, L
"You have a non-default setting of UseLibgit2_mask in your registry.\n\nThis might be the case in order to resolve an issue in an older TortoiseGit version.\n\nDo you want to restore the default value (i.e., remove custom setting from registry)?", L
"TortoiseGit", MB_ICONQUESTION
| MB_YESNO
) == IDYES
)
575 CRegStdDWORD(L
"Software\\TortoiseGit\\UseLibgit2_mask").removeValue();
578 CMessageBox::RemoveRegistryKey(L
"OldMsysgitVersionWarning");
580 CRegDWORD checkNewerWeekDay
= CRegDWORD(L
"Software\\TortoiseGit\\CheckNewerWeekDay", 0);
581 if (!checkNewerWeekDay
.exists() || lVersion
<= 0x01081000)
583 std::random_device rd
;
584 std::mt19937
mt(rd());
585 std::uniform_int_distribution
<int> dist(0, 6);
586 checkNewerWeekDay
= dist(mt
);
589 // version specific updates
590 if (lVersion
<= 0x02020100)
592 CString username
= CRegString(L
"Software\\TortoiseGit\\TortoiseProc\\SendMail\\Username", L
"");
593 CString password
= CRegString(L
"Software\\TortoiseGit\\TortoiseProc\\SendMail\\Password", L
"");
594 if (!username
.IsEmpty() && !password
.IsEmpty())
596 if (CWindowsCredentialsStore::SaveCredential(L
"TortoiseGit:SMTP-Credentials", username
, password
) == 0)
598 CRegString(L
"Software\\TortoiseGit\\TortoiseProc\\SendMail\\Username").removeValue();
599 CRegString(L
"Software\\TortoiseGit\\TortoiseProc\\SendMail\\Password").removeValue();
602 for (const CString
& setting
: { L
"SyncIn", L
"SyncOut" })
604 CRegDWORD
reg(L
"Software\\TortoiseGit\\StatusColumns\\" + setting
+ L
"loglistVersion", 0xff);
610 if (lVersion
<= 0x02010500)
612 // We updated GITSLC_COL_VERSION, but only significant changes were made for GitStatusList
613 // so, smoothly migrate GitLoglistBase settings
614 for (const CString
& setting
: { L
"log", L
"Blame", L
"Rebase", L
"reflog", L
"SyncIn", L
"SyncOut" })
616 CRegDWORD
reg(L
"Software\\TortoiseGit\\StatusColumns\\" + setting
+ L
"loglistVersion", 0xff);
622 if (lVersion
<= 0x01090000)
624 if (CRegDWORD(L
"Software\\TortoiseGit\\TGitCacheCheckContent", TRUE
) == FALSE
)
626 CRegDWORD(L
"Software\\TortoiseGit\\TGitCacheCheckContentMaxSize") = 0;
627 CRegDWORD(L
"Software\\TortoiseGit\\TGitCacheCheckContent").removeValue();
631 if (lVersion
<= 0x01080801)
633 CRegStdDWORD(L
"Software\\TortoiseGit\\StatusColumns\\BrowseRefs").removeValue();
634 CRegStdString(L
"Software\\TortoiseGit\\StatusColumns\\BrowseRefs_Order").removeValue();
635 CRegStdString(L
"Software\\TortoiseGit\\StatusColumns\\BrowseRefs_Width").removeValue();
638 if (lVersion
<= 0x01080401)
640 if (CRegStdDWORD(L
"Software\\TortoiseGit\\TortoiseProc\\SendMail\\UseMAPI", FALSE
) == TRUE
)
641 CRegStdDWORD(L
"Software\\TortoiseGit\\TortoiseProc\\SendMail\\DeliveryType") = SEND_MAIL_MAPI
;
642 CRegStdDWORD(L
"Software\\TortoiseGit\\TortoiseProc\\SendMail\\UseMAPI").removeValue();
645 if (lVersion
<= 0x01080202)
647 // upgrade to 1.8.3: force recreation of all diff scripts.
648 CAppUtils::SetupDiffScripts(true, CString());
651 if (lVersion
<= 0x01080100)
653 if (CRegStdDWORD(L
"Software\\TortoiseGit\\LogTopoOrder", TRUE
) == FALSE
)
654 CRegStdDWORD(L
"Software\\TortoiseGit\\LogOrderBy") = 0;
656 // smoothly migrate broken msysgit path settings
657 CString oldmsysGitSetting
= CRegString(REG_MSYSGIT_PATH
);
658 oldmsysGitSetting
.TrimRight(L
'\\');
659 if (oldmsysGitSetting
.GetLength() > 4 && CStringUtils::EndsWith(oldmsysGitSetting
, L
"\\cmd"))
661 CString newPath
= oldmsysGitSetting
.Mid(0, oldmsysGitSetting
.GetLength() - 3) + L
"bin";
662 if (PathFileExists(newPath
+ L
"\\git.exe"))
664 CRegString(REG_MSYSGIT_PATH
) = newPath
;
665 g_Git
.m_bInitialized
= FALSE
;
666 g_Git
.CheckMsysGitDir();
671 if (lVersion
<= 0x01040000)
673 CRegStdDWORD(L
"Software\\TortoiseGit\\OwnerdrawnMenus").removeValue();
676 if (lVersion
<= 0x01070600)
678 CoInitialize(nullptr);
681 CRegStdDWORD(L
"Software\\TortoiseGit\\ConvertBase").removeValue();
682 CRegStdDWORD(L
"Software\\TortoiseGit\\DiffProps").removeValue();
683 if (CRegStdDWORD(L
"Software\\TortoiseGit\\CheckNewer", TRUE
) == FALSE
)
684 CRegStdDWORD(L
"Software\\TortoiseGit\\VersionCheck") = FALSE
;
685 CRegStdDWORD(L
"Software\\TortoiseGit\\CheckNewer").removeValue();
688 CTraceToOutputDebugString::Instance()(_T(__FUNCTION__
) L
": Setting up diff scripts ...\n");
689 CAppUtils::SetupDiffScripts(false, CString());
691 // set the current version so we don't come here again until the next update!
692 regVersion
= _T(STRPRODUCTVER
);
695 void CTortoiseProcApp::InitializeJumpList(const CString
& appid
)
697 // for Win7 : use a custom jump list
698 CoInitialize(nullptr);
700 DeleteJumpList(appid
);
701 DoInitializeJumpList(appid
);
705 void CTortoiseProcApp::DoInitializeJumpList(const CString
& appid
)
707 ATL::CComPtr
<ICustomDestinationList
> pcdl
;
708 HRESULT hr
= pcdl
.CoCreateInstance(CLSID_DestinationList
, nullptr, CLSCTX_INPROC_SERVER
);
712 hr
= pcdl
->SetAppID(appid
);
717 ATL::CComPtr
<IObjectArray
> poaRemoved
;
718 hr
= pcdl
->BeginList(&uMaxSlots
, IID_PPV_ARGS(&poaRemoved
));
722 ATL::CComPtr
<IObjectCollection
> poc
;
723 hr
= poc
.CoCreateInstance(CLSID_EnumerableObjectCollection
, nullptr, CLSCTX_INPROC_SERVER
);
727 CString sTemp
= CString(MAKEINTRESOURCE(IDS_MENUSETTINGS
));
728 CStringUtils::RemoveAccelerators(sTemp
);
730 ATL::CComPtr
<IShellLink
> psl
;
731 hr
= CreateShellLink(L
"/command:settings", (LPCTSTR
)sTemp
, 20, &psl
);
735 sTemp
= CString(MAKEINTRESOURCE(IDS_MENUHELP
));
736 CStringUtils::RemoveAccelerators(sTemp
);
737 psl
.Release(); // Need to release the object before calling operator&()
738 hr
= CreateShellLink(L
"/command:help", (LPCTSTR
)sTemp
, 19, &psl
);
743 ATL::CComPtr
<IObjectArray
> poa
;
744 hr
= poc
.QueryInterface(&poa
);
746 pcdl
->AppendCategory((LPCTSTR
)CString(MAKEINTRESOURCE(IDS_PROC_TASKS
)), poa
);
751 int CTortoiseProcApp::ExitInstance()
753 SYS_IMAGE_LIST().Cleanup();
754 Gdiplus::GdiplusShutdown(m_gdiplusToken
);
756 CWinAppEx::ExitInstance();
762 void CTortoiseProcApp::CheckForNewerVersion()
764 // check for newer versions
765 if (CRegDWORD(L
"Software\\TortoiseGit\\VersionCheck", TRUE
) != FALSE
)
771 if ((now
!= 0) && (localtime_s(&ptm
, &now
)==0))
774 // Check daily for new preview releases
775 CRegDWORD oldday
= CRegDWORD(L
"Software\\TortoiseGit\\CheckNewerDay", (DWORD
)-1);
776 if (((DWORD
)oldday
) == -1)
777 oldday
= ptm
.tm_yday
;
780 if ((DWORD
)oldday
!= (DWORD
)ptm
.tm_yday
)
782 oldday
= ptm
.tm_yday
;
785 // we don't calculate the real 'week of the year' here
786 // because just to decide if we should check for an update
787 // that's not needed.
788 week
= (ptm
.tm_yday
+ CRegDWORD(L
"Software\\TortoiseGit\\CheckNewerWeekDay", 0)) / 7;
790 CRegDWORD oldweek
= CRegDWORD(L
"Software\\TortoiseGit\\CheckNewerWeek", (DWORD
)-1);
791 if (((DWORD
)oldweek
) == -1)
792 oldweek
= week
; // first start of TortoiseProc, no update check needed
795 if ((DWORD
)week
!= oldweek
)
799 CAppUtils::RunTortoiseGitProc(L
"/command:updatecheck", false, false);