1 // TortoiseGit - a Windows shell extension for easy version control
3 // Copyright (C) 2008-2015 - 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 "Libraries.h"
41 #include "TaskbarUUID.h"
42 #include "ProjectProperties.h"
43 #include "HistoryCombo.h"
48 #define STRUCT_IOVEC_DEFINED
54 #pragma comment(linker, "\"/manifestdependency:type='win32' name='Microsoft.Windows.Common-Controls' version='6.0.0.0' processorArchitecture='*' publicKeyToken='6595b64144ccf1df' language='*'\"")
56 BEGIN_MESSAGE_MAP(CTortoiseProcApp
, CWinAppEx
)
57 ON_COMMAND(ID_HELP
, CWinAppEx::OnHelp
)
60 //////////////////////////////////////////////////////////////////////////
62 CTortoiseProcApp::CTortoiseProcApp()
64 CTraceToOutputDebugString::Instance()(_T(__FUNCTION__
) _T(": Constructor\n"));
66 // prevent from inheriting %GIT_DIR% from parent process by resetting it,
67 // use MSVC function instead of Windows API because MSVC runtime caches environment variables
68 _tputenv(_T("GIT_DIR="));
69 CCrashReport::Instance().AddUserInfoToReport(L
"CommandLine", GetCommandLine());
74 CGit::SetGit2CredentialCallback(CAppUtils::Git2GetUserPassword
);
75 CGit::SetGit2CertificateCheckCertificate(CAppUtils::Git2CertificateCheck
);
76 m_bLoadUserToolbars
= FALSE
;
79 m_gdiplusToken
= NULL
;
80 #if defined (_WIN64) && _MSC_VER >= 1800
85 CTortoiseProcApp::~CTortoiseProcApp()
88 SYS_IMAGE_LIST().Cleanup();
89 git_libgit2_shutdown();
92 // The one and only CTortoiseProcApp object
93 CTortoiseProcApp theApp
;
95 CString g_sGroupingUUID
;
96 CString g_sGroupingIcon
;
97 bool g_bGroupingRemoveIcon
= false;
99 CGitIndexFileMap g_IndexFileMap
;
101 #if ENABLE_CRASHHANLDER
102 CCrashReportTGit
crasher(L
"TortoiseGit " _T(APP_X64_STRING
), TGIT_VERMAJOR
, TGIT_VERMINOR
, TGIT_VERMICRO
, TGIT_VERBUILD
, TGIT_VERDATE
);
105 // CTortoiseProcApp initialization
107 BOOL
CTortoiseProcApp::InitInstance()
109 CTraceToOutputDebugString::Instance()(_T(__FUNCTION__
) _T(": InitInstance\n"));
111 CMFCVisualManager::SetDefaultManager(RUNTIME_CLASS(CMFCVisualManagerWindows
));
112 CMFCButton::EnableWindowsTheming();
113 CHistoryCombo::m_nGitIconIndex
= SYS_IMAGE_LIST().AddIcon((HICON
)LoadImage(AfxGetResourceHandle(), MAKEINTRESOURCE(IDI_GITCONFIG
), IMAGE_ICON
, 0, 0, LR_DEFAULTSIZE
));
115 Gdiplus::GdiplusStartupInput gdiplusStartupInput
;
116 Gdiplus::GdiplusStartup(&m_gdiplusToken
,&gdiplusStartupInput
,NULL
);
118 //set the resource dll for the required language
119 CRegDWORD loc
= CRegDWORD(_T("Software\\TortoiseGit\\LanguageID"), 1033);
123 langStr
.Format(_T("%ld"), langId
);
124 CCrashReport::Instance().AddUserInfoToReport(L
"LanguageID", langStr
);
127 CStringA langpath
= CStringA(CPathUtils::GetAppParentDirectory());
128 langpath
+= "Languages";
131 langDll
.Format(_T("%sLanguages\\TortoiseProc%ld.dll"), (LPCTSTR
)CPathUtils::GetAppParentDirectory(), langId
);
133 CString sVer
= _T(STRPRODUCTVER
);
134 CString sFileVer
= CPathUtils::GetVersionFromFile(langDll
);
135 if (sFileVer
== sVer
)
137 HINSTANCE hInst
= LoadLibrary(langDll
);
140 CTraceToOutputDebugString::Instance()(_T(__FUNCTION__
) _T(": Load Language DLL %s\n"), langDll
);
141 AfxSetResourceHandle(hInst
);
146 DWORD lid
= SUBLANGID(langId
);
150 langId
= MAKELANGID(PRIMARYLANGID(langId
), lid
);
155 } while (langId
!= 0);
156 TCHAR buf
[6] = { 0 };
157 _tcscpy_s(buf
, _T("en"));
159 // MFC uses a help file with the same name as the application by default,
160 // which means we have to change that default to our language specific help files
161 CString sHelppath
= CPathUtils::GetAppDirectory() + _T("TortoiseGit_en.chm");
162 free((void*)m_pszHelpFilePath
);
163 m_pszHelpFilePath
=_tcsdup(sHelppath
);
164 sHelppath
= CPathUtils::GetAppParentDirectory() + _T("Languages\\TortoiseGit_en.chm");
167 CString sLang
= _T("_");
168 if (GetLocaleInfo(MAKELCID(langId
, SORT_DEFAULT
), LOCALE_SISO639LANGNAME
, buf
, _countof(buf
)))
171 sHelppath
.Replace(_T("_en"), sLang
);
172 if (PathFileExists(sHelppath
))
174 free((void*)m_pszHelpFilePath
);
175 m_pszHelpFilePath
=_tcsdup(sHelppath
);
179 sHelppath
.Replace(sLang
, _T("_en"));
180 if (GetLocaleInfo(MAKELCID(langId
, SORT_DEFAULT
), LOCALE_SISO3166CTRYNAME
, buf
, _countof(buf
)))
184 sHelppath
.Replace(_T("_en"), sLang
);
185 if (PathFileExists(sHelppath
))
187 free((void*)m_pszHelpFilePath
);
188 m_pszHelpFilePath
=_tcsdup(sHelppath
);
192 sHelppath
.Replace(sLang
, _T("_en"));
194 DWORD lid
= SUBLANGID(langId
);
198 langId
= MAKELANGID(PRIMARYLANGID(langId
), lid
);
203 CTraceToOutputDebugString::Instance()(_T(__FUNCTION__
) _T(": Set Help Filename %s\n"), m_pszHelpFilePath
);
204 setlocale(LC_ALL
, "");
206 if (!g_Git
.CheckMsysGitDir())
208 UINT ret
= CMessageBox::Show(NULL
, IDS_PROC_NOMSYSGIT
, IDS_APPNAME
, 3, IDI_HAND
, IDS_PROC_SETMSYSGITPATH
, IDS_PROC_GOTOMSYSGITWEBSITE
, IDS_ABORTBUTTON
);
211 ShellExecute(nullptr, _T("open"), _T("https://git-for-windows.github.io/"), nullptr, nullptr, SW_SHOW
);
215 // open settings dialog
216 CSinglePropSheetDlg(CString(MAKEINTRESOURCE(IDS_PROC_SETTINGS_TITLE
)), new CSetMainPage(), this->GetMainWnd()).DoModal();
220 if (CAppUtils::GetMsysgitVersion() < 0x01090500)
222 int ret
= CMessageBox::ShowCheck(NULL
, IDS_PROC_OLDMSYSGIT
, IDS_APPNAME
, 1, IDI_EXCLAMATION
, IDS_PROC_GOTOMSYSGITWEBSITE
, IDS_ABORTBUTTON
, IDS_IGNOREBUTTON
, _T("OldMsysgitVersionWarning"), IDS_PROC_NOTSHOWAGAINIGNORE
);
225 CMessageBox::RemoveRegistryKey(_T("OldMsysgitVersionWarning")); // only store answer if it is "Ignore"
226 ShellExecute(nullptr, _T("open"), _T("https://git-for-windows.github.io/"), nullptr, nullptr, SW_SHOW
);
231 CMessageBox::RemoveRegistryKey(_T("OldMsysgitVersionWarning")); // only store answer if it is "Ignore"
237 CTraceToOutputDebugString::Instance()(_T(__FUNCTION__
) _T(": Registering Crash Report ...\n"));
238 CCrashReport::Instance().AddUserInfoToReport(L
"msysGitDir", CGit::ms_LastMsysGitDir
);
239 CString versionString
;
240 versionString
.Format(_T("%d"), CGit::ms_LastMsysGitVersion
);
241 CCrashReport::Instance().AddUserInfoToReport(L
"msysGitVersion", versionString
);
244 CTraceToOutputDebugString::Instance()(_T(__FUNCTION__
) _T(": Initializing UI components ...\n"));
245 // InitCommonControls() is required on Windows XP if an application
246 // manifest specifies use of ComCtl32.dll version 6 or later to enable
247 // visual styles. Otherwise, any window creation will fail.
249 INITCOMMONCONTROLSEX used
= {
250 sizeof(INITCOMMONCONTROLSEX
),
251 ICC_ANIMATE_CLASS
| ICC_BAR_CLASSES
| ICC_COOL_CLASSES
| ICC_DATE_CLASSES
|
252 ICC_HOTKEY_CLASS
| ICC_INTERNET_CLASSES
| ICC_LISTVIEW_CLASSES
|
253 ICC_NATIVEFNTCTL_CLASS
| ICC_PAGESCROLLER_CLASS
| ICC_PROGRESS_CLASS
|
254 ICC_TAB_CLASSES
| ICC_TREEVIEW_CLASSES
| ICC_UPDOWN_CLASS
|
255 ICC_USEREX_CLASSES
| ICC_WIN95_CLASSES
257 InitCommonControlsEx(&used
);
259 AfxEnableControlContainer();
261 CWinAppEx::InitInstance();
262 SetRegistryKey(_T("TortoiseGit"));
263 AfxGetApp()->m_pszProfileName
= _tcsdup(_T("TortoiseProc")); // w/o this ResizableLib will store data under TortoiseGitProc which is not compatible with older versions
265 CCmdLineParser
parser(AfxGetApp()->m_lpCmdLine
);
268 CString sVal
= parser
.GetVal(_T("hwnd"));
270 hWndExplorer
= (HWND
)_wcstoui64(sVal
, nullptr, 16);
272 while (GetParent(hWndExplorer
)!=NULL
)
273 hWndExplorer
= GetParent(hWndExplorer
);
274 if (!IsWindow(hWndExplorer
))
279 // if HKCU\Software\TortoiseGit\Debug is not 0, show our command line
281 if (CRegDWORD(_T("Software\\TortoiseGit\\Debug"), FALSE
)==TRUE
)
282 AfxMessageBox(AfxGetApp()->m_lpCmdLine
, MB_OK
| MB_ICONINFORMATION
);
284 if (parser
.HasKey(_T("urlhandler")))
286 CString url
= parser
.GetVal(_T("urlhandler"));
287 if (url
.Find(_T("tgit://clone/")) == 0)
289 url
= url
.Mid(13); // 21 = "tgit://clone/".GetLength()
291 else if (url
.Find(_T("github-windows://openRepo/")) == 0)
293 url
= url
.Mid(26); // 26 = "github-windows://openRepo/".GetLength()
294 int questioMark
= url
.Find('?');
296 url
= url
.Left(questioMark
);
298 else if (url
.Find(_T("smartgit://cloneRepo/")) == 0)
300 url
= url
.Mid(21); // 21 = "smartgit://cloneRepo/".GetLength()
304 CMessageBox::Show(NULL
, IDS_ERR_INVALIDPATH
, IDS_APPNAME
, MB_ICONERROR
);
308 newCmd
.Format(_T("/command:clone /url:\"%s\" /hasurlhandler"), (LPCTSTR
)url
);
309 parser
= CCmdLineParser(newCmd
);
312 if ( parser
.HasKey(_T("path")) && parser
.HasKey(_T("pathfile")))
314 CMessageBox::Show(NULL
, IDS_ERR_INVALIDPATH
, IDS_APPNAME
, MB_ICONERROR
);
318 CTGitPath cmdLinePath
;
319 CTGitPathList pathList
;
320 if (g_sGroupingUUID
.IsEmpty())
321 g_sGroupingUUID
= parser
.GetVal(L
"groupuuid");
322 if ( parser
.HasKey(_T("pathfile")) )
325 CString sPathfileArgument
= CPathUtils::GetLongPathname(parser
.GetVal(_T("pathfile")));
327 cmdLinePath
.SetFromUnknown(sPathfileArgument
);
328 if (pathList
.LoadFromFile(cmdLinePath
)==false)
329 return FALSE
; // no path specified!
330 if ( parser
.HasKey(_T("deletepathfile")) )
332 // We can delete the temporary path file, now that we've loaded it
333 ::DeleteFile(cmdLinePath
.GetWinPath());
335 // This was a path to a temporary file - it's got no meaning now, and
336 // anybody who uses it again is in for a problem...
343 CString sPathArgument
= CPathUtils::GetLongPathname(parser
.GetVal(_T("path")));
344 if (parser
.HasKey(_T("expaths")))
346 // an /expaths param means we're started via the buttons in our Win7 library
347 // and that means the value of /expaths is the current directory, and
348 // the selected paths are then added as additional parameters but without a key, only a value
350 // because of the "strange treatment of quotation marks and backslashes by CommandLineToArgvW"
351 // we have to escape the backslashes first. Since we're only dealing with paths here, that's
353 // Without this, a command line like:
354 // /command:commit /expaths:"D:\" "D:\Utils"
355 // would fail because the "D:\" is treated as the backslash being the escape char for the quotation
356 // mark and we'd end up with:
357 // argv[1] = /command:commit
358 // argv[2] = /expaths:D:" D:\Utils
359 // See here for more details: http://blogs.msdn.com/b/oldnewthing/archive/2010/09/17/10063629.aspx
360 CString cmdLine
= GetCommandLineW();
361 cmdLine
.Replace(L
"\\", L
"\\\\");
363 LPWSTR
*szArglist
= CommandLineToArgvW(cmdLine
, &nArgs
);
366 // argument 0 is the process path, so start with 1
367 for (int i
= 1; i
< nArgs
; ++i
)
369 if (szArglist
[i
][0] != '/')
371 if (!sPathArgument
.IsEmpty())
372 sPathArgument
+= '*';
373 sPathArgument
+= szArglist
[i
];
376 sPathArgument
.Replace(L
"\\\\", L
"\\");
378 LocalFree(szArglist
);
380 if (sPathArgument
.IsEmpty() && parser
.HasKey(L
"path"))
382 CMessageBox::Show(hWndExplorer
, IDS_ERR_INVALIDPATH
, IDS_APPNAME
, MB_ICONERROR
);
385 int asterisk
= sPathArgument
.Find('*');
386 cmdLinePath
.SetFromUnknown(asterisk
>= 0 ? sPathArgument
.Left(asterisk
) : sPathArgument
);
387 pathList
.LoadFromAsteriskSeparatedString(sPathArgument
);
390 if (pathList
.IsEmpty()) {
391 pathList
.AddPath(CTGitPath::CTGitPath(g_Git
.m_CurrentDir
));
394 // Set CWD to temporary dir, and restore it later
396 DWORD len
= GetCurrentDirectory(0, NULL
);
399 std::unique_ptr
<TCHAR
[]> originalCurrentDirectory(new TCHAR
[len
]);
400 if (GetCurrentDirectory(len
, originalCurrentDirectory
.get()))
402 sOrigCWD
= originalCurrentDirectory
.get();
403 sOrigCWD
= CPathUtils::GetLongPathname(sOrigCWD
);
406 TCHAR pathbuf
[MAX_PATH
] = {0};
407 GetTortoiseGitTempPath(MAX_PATH
, pathbuf
);
408 SetCurrentDirectory(pathbuf
);
411 CheckForNewerVersion();
413 CAutoGeneralHandle TGitMutex
= ::CreateMutex(NULL
, FALSE
, _T("TortoiseGitProc.exe"));
414 if (!g_Git
.SetCurrentDir(cmdLinePath
.GetWinPathString(), parser
.HasKey(_T("submodule")) == TRUE
))
416 for (int i
= 0; i
< pathList
.GetCount(); ++i
)
417 if(g_Git
.SetCurrentDir(pathList
[i
].GetWinPath()))
421 if(!g_Git
.m_CurrentDir
.IsEmpty())
423 sOrigCWD
= g_Git
.m_CurrentDir
;
424 SetCurrentDirectory(g_Git
.m_CurrentDir
);
427 if (g_sGroupingUUID
.IsEmpty())
429 CRegStdDWORD groupSetting
= CRegStdDWORD(_T("Software\\TortoiseGit\\GroupTaskbarIconsPerRepo"), 3);
430 switch (DWORD(groupSetting
))
434 // implemented differently to TortoiseSVN atm
440 if (GitAdminDir::HasAdminDir(g_Git
.m_CurrentDir
, true, &wcroot
))
443 CStringA
wcRootA(wcroot
+ CPathUtils::GetAppDirectory());
444 if (!git_odb_hash(&oid
, wcRootA
, wcRootA
.GetLength(), GIT_OBJ_BLOB
))
447 git_oid_tostr(hash
.GetBufferSetLength(GIT_OID_HEXSZ
+ 1), GIT_OID_HEXSZ
+ 1, &oid
);
448 hash
.ReleaseBuffer();
449 g_sGroupingUUID
= hash
;
451 ProjectProperties pp
;
453 CString icon
= pp
.sIcon
;
454 icon
.Replace('/', '\\');
456 g_bGroupingRemoveIcon
= true;
457 g_sGroupingIcon
= icon
;
463 CString sAppID
= GetTaskIDPerUUID(g_sGroupingUUID
).c_str();
464 InitializeJumpList(sAppID
);
465 EnsureGitLibrary(false);
471 // requires CWD to be set
472 CGit::m_LogEncode
= CAppUtils::GetLogOutputEncode();
474 // make sure all config files are read in order to check that none contains an error
475 g_Git
.GetConfigValue(_T("doesnot.exist"));
484 UINT choice
= CMessageBox::Show(hWndExplorer
, err
, _T("TortoiseGit"), 1, IDI_ERROR
, CString(MAKEINTRESOURCE(IDS_PROC_EDITLOCALGITCONFIG
)), CString(MAKEINTRESOURCE(IDS_PROC_EDITGLOBALGITCONFIG
)), CString(MAKEINTRESOURCE(IDS_ABORTBUTTON
)));
487 // open the config file with alternative editor
488 CAppUtils::LaunchAlternativeEditor(g_Git
.GetGitLocalConfig());
490 else if (choice
== 2)
492 // open the global config file with alternative editor
493 CAppUtils::LaunchAlternativeEditor(g_Git
.GetGitGlobalConfig());
499 // execute the requested command
500 CommandServer server
;
501 Command
* cmd
= server
.GetCommand(parser
.GetVal(_T("command")));
504 cmd
->SetExplorerHwnd(hWndExplorer
);
506 cmd
->SetParser(parser
);
507 cmd
->SetPaths(pathList
, cmdLinePath
);
509 retSuccess
= cmd
->Execute();
513 // Look for temporary files left around by TortoiseSVN and
514 // remove them. But only delete 'old' files because some
515 // apps might still be needing the recent ones.
517 DWORD len
= GetTortoiseGitTempPath(0, NULL
);
518 std::unique_ptr
<TCHAR
[]> path(new TCHAR
[len
+ 100]);
519 len
= GetTortoiseGitTempPath (len
+ 100, path
.get());
522 CDirFileEnum
finder(path
.get());
524 ::GetSystemTimeAsFileTime(&systime_
);
525 __int64 systime
= (((_int64
)systime_
.dwHighDateTime
)<<32) | ((__int64
)systime_
.dwLowDateTime
);
528 while (finder
.NextFile(filepath
, &isDir
))
530 HANDLE hFile
= ::CreateFile(filepath
, GENERIC_READ
, FILE_SHARE_READ
, NULL
, OPEN_EXISTING
, isDir
? FILE_FLAG_BACKUP_SEMANTICS
: NULL
, NULL
);
531 if (hFile
!= INVALID_HANDLE_VALUE
)
533 FILETIME createtime_
;
534 if (::GetFileTime(hFile
, &createtime_
, NULL
, NULL
))
536 ::CloseHandle(hFile
);
537 __int64 createtime
= (((_int64
)createtime_
.dwHighDateTime
)<<32) | ((__int64
)createtime_
.dwLowDateTime
);
538 if ((createtime
+ 864000000000) < systime
) //only delete files older than a day
540 ::SetFileAttributes(filepath
, FILE_ATTRIBUTE_NORMAL
);
542 ::RemoveDirectory(filepath
);
544 ::DeleteFile(filepath
);
548 ::CloseHandle(hFile
);
554 // Since the dialog has been closed, return FALSE so that we exit the
555 // application, rather than start the application's message pump.
559 void CTortoiseProcApp::CheckUpgrade()
561 CRegString regVersion
= CRegString(_T("Software\\TortoiseGit\\CurrentVersion"));
562 CString sVersion
= regVersion
;
563 CTraceToOutputDebugString::Instance()(_T(__FUNCTION__
) _T(": Current TGit Version %s\n"), (LPCTSTR
)sVersion
);
564 if (sVersion
.Compare(_T(STRPRODUCTVER
))==0)
566 // we're starting the first time with a new version!
569 int pos
= sVersion
.Find('.');
572 lVersion
= (_ttol(sVersion
.Left(pos
))<<24);
573 lVersion
|= (_ttol(sVersion
.Mid(pos
+1))<<16);
574 pos
= sVersion
.Find('.', pos
+1);
575 lVersion
|= (_ttol(sVersion
.Mid(pos
+1))<<8);
579 pos
= sVersion
.Find(',');
582 lVersion
= (_ttol(sVersion
.Left(pos
))<<24);
583 lVersion
|= (_ttol(sVersion
.Mid(pos
+1))<<16);
584 pos
= sVersion
.Find(',', pos
+1);
585 lVersion
|= (_ttol(sVersion
.Mid(pos
+1))<<8);
590 if (CRegStdDWORD(_T("Software\\TortoiseGit\\UseLibgit2"), TRUE
) != TRUE
)
592 if (CMessageBox::Show(nullptr, _T("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)?"), _T("TortoiseGit"), MB_ICONQUESTION
| MB_YESNO
) == IDYES
)
593 CRegStdDWORD(_T("Software\\TortoiseGit\\UseLibgit2")).removeValue();
596 if (CRegStdDWORD(_T("Software\\TortoiseGit\\UseLibgit2_mask")).exists())
598 if (CMessageBox::Show(nullptr, _T("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)?"), _T("TortoiseGit"), MB_ICONQUESTION
| MB_YESNO
) == IDYES
)
599 CRegStdDWORD(_T("Software\\TortoiseGit\\UseLibgit2_mask")).removeValue();
602 CMessageBox::RemoveRegistryKey(_T("OldMsysgitVersionWarning"));
604 srand((unsigned)time(0));
605 CRegDWORD checkNewerWeekDay
= CRegDWORD(_T("Software\\TortoiseGit\\CheckNewerWeekDay"), 0);
606 if (!checkNewerWeekDay
.exists())
607 checkNewerWeekDay
= rand() % 7;
609 // version specific updates
610 if (lVersion
<= 0x01080802)
612 CRegStdDWORD(_T("Software\\TortoiseGit\\TortoiseProc\\ResizableState\\CleanTypeDlgWindowPlacement")).removeValue();
615 if (lVersion
<= 0x01080801)
617 CRegStdDWORD(_T("Software\\TortoiseGit\\StatusColumns\\BrowseRefs")).removeValue();
618 CRegStdString(_T("Software\\TortoiseGit\\StatusColumns\\BrowseRefs_Order")).removeValue();
619 CRegStdString(_T("Software\\TortoiseGit\\StatusColumns\\BrowseRefs_Width")).removeValue();
622 if (lVersion
<= 0x01080401)
624 if (CRegStdDWORD(_T("Software\\TortoiseGit\\TortoiseProc\\SendMail\\UseMAPI"), FALSE
) == TRUE
)
625 CRegStdDWORD(_T("Software\\TortoiseGit\\TortoiseProc\\SendMail\\DeliveryType")) = SEND_MAIL_MAPI
;
626 CRegStdDWORD(_T("Software\\TortoiseGit\\TortoiseProc\\SendMail\\UseMAPI")).removeValue();
629 if (lVersion
<= 0x01080202)
631 // upgrade to 1.8.3: force recreation of all diff scripts.
632 CAppUtils::SetupDiffScripts(true, CString());
635 if (lVersion
<= 0x01080100)
637 if (CRegStdDWORD(_T("Software\\TortoiseGit\\LogTopoOrder"), TRUE
) == FALSE
)
638 CRegStdDWORD(_T("Software\\TortoiseGit\\LogOrderBy")) = 0;
640 // smoothly migrate broken msysgit path settings
641 CString oldmsysGitSetting
= CRegString(REG_MSYSGIT_PATH
);
642 oldmsysGitSetting
.TrimRight(_T("\\"));
643 CString right
= oldmsysGitSetting
.Right(4);
644 if (oldmsysGitSetting
.GetLength() > 4 && oldmsysGitSetting
.Right(4) == _T("\\cmd"))
646 CString newPath
= oldmsysGitSetting
.Mid(0, oldmsysGitSetting
.GetLength() - 3) + _T("bin");
647 if (PathFileExists(newPath
+ _T("\\git.exe")))
649 CRegString(REG_MSYSGIT_PATH
) = newPath
;
650 g_Git
.m_bInitialized
= FALSE
;
651 g_Git
.CheckMsysGitDir();
656 if (lVersion
<= 0x01040000)
658 CRegStdDWORD(_T("Software\\TortoiseGit\\OwnerdrawnMenus")).removeValue();
661 if (lVersion
<= 0x01070600)
666 CRegStdDWORD(_T("Software\\TortoiseGit\\ConvertBase")).removeValue();
667 CRegStdDWORD(_T("Software\\TortoiseGit\\DiffProps")).removeValue();
668 if (CRegStdDWORD(_T("Software\\TortoiseGit\\CheckNewer"), TRUE
) == FALSE
)
669 CRegStdDWORD(_T("Software\\TortoiseGit\\VersionCheck")) = FALSE
;
670 CRegStdDWORD(_T("Software\\TortoiseGit\\CheckNewer")).removeValue();
673 CTraceToOutputDebugString::Instance()(_T(__FUNCTION__
) _T(": Setting up diff scripts ...\n"));
674 CAppUtils::SetupDiffScripts(false, CString());
676 // set the current version so we don't come here again until the next update!
677 regVersion
= _T(STRPRODUCTVER
);
680 void CTortoiseProcApp::InitializeJumpList(const CString
& appid
)
682 // for Win7 : use a custom jump list
685 DeleteJumpList(appid
);
686 DoInitializeJumpList(appid
);
690 void CTortoiseProcApp::DoInitializeJumpList(const CString
& appid
)
692 ATL::CComPtr
<ICustomDestinationList
> pcdl
;
693 HRESULT hr
= pcdl
.CoCreateInstance(CLSID_DestinationList
, NULL
, CLSCTX_INPROC_SERVER
);
697 hr
= pcdl
->SetAppID(appid
);
702 ATL::CComPtr
<IObjectArray
> poaRemoved
;
703 hr
= pcdl
->BeginList(&uMaxSlots
, IID_PPV_ARGS(&poaRemoved
));
707 ATL::CComPtr
<IObjectCollection
> poc
;
708 hr
= poc
.CoCreateInstance(CLSID_EnumerableObjectCollection
, NULL
, CLSCTX_INPROC_SERVER
);
712 CString sTemp
= CString(MAKEINTRESOURCE(IDS_MENUSETTINGS
));
713 CStringUtils::RemoveAccelerators(sTemp
);
715 ATL::CComPtr
<IShellLink
> psl
;
716 hr
= CreateShellLink(_T("/command:settings"), (LPCTSTR
)sTemp
, 20, &psl
);
720 sTemp
= CString(MAKEINTRESOURCE(IDS_MENUHELP
));
721 CStringUtils::RemoveAccelerators(sTemp
);
722 psl
.Release(); // Need to release the object before calling operator&()
723 hr
= CreateShellLink(_T("/command:help"), (LPCTSTR
)sTemp
, 19, &psl
);
728 ATL::CComPtr
<IObjectArray
> poa
;
729 hr
= poc
.QueryInterface(&poa
);
731 pcdl
->AppendCategory((LPCTSTR
)CString(MAKEINTRESOURCE(IDS_PROC_TASKS
)), poa
);
736 int CTortoiseProcApp::ExitInstance()
738 Gdiplus::GdiplusShutdown(m_gdiplusToken
);
740 CWinAppEx::ExitInstance();
746 void CTortoiseProcApp::CheckForNewerVersion()
748 // check for newer versions
749 if (CRegDWORD(_T("Software\\TortoiseGit\\VersionCheck"), TRUE
) != FALSE
)
755 if ((now
!= 0) && (localtime_s(&ptm
, &now
)==0))
758 // Check daily for new preview releases
759 CRegDWORD oldday
= CRegDWORD(_T("Software\\TortoiseGit\\CheckNewerDay"), (DWORD
)-1);
760 if (((DWORD
)oldday
) == -1)
761 oldday
= ptm
.tm_yday
;
764 if ((DWORD
)oldday
!= (DWORD
)ptm
.tm_yday
)
766 oldday
= ptm
.tm_yday
;
769 // we don't calculate the real 'week of the year' here
770 // because just to decide if we should check for an update
771 // that's not needed.
772 week
= (ptm
.tm_yday
+ CRegDWORD(_T("Software\\TortoiseGit\\CheckNewerWeekDay"), 0)) / 7;
774 CRegDWORD oldweek
= CRegDWORD(_T("Software\\TortoiseGit\\CheckNewerWeek"), (DWORD
)-1);
775 if (((DWORD
)oldweek
) == -1)
776 oldweek
= week
; // first start of TortoiseProc, no update check needed
779 if ((DWORD
)week
!= oldweek
)
783 CAppUtils::RunTortoiseGitProc(_T("/command:updatecheck"), false, false);