1
// TortoiseGit - a Windows shell extension for easy version control
3 // Copyright (C) 2012-2018 - TortoiseGit
4 // Copyright (C) 2003-2017 - 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 "ShellCache.h"
22 #include "GitAdminDir.h"
24 ShellCache::ShellCache()
26 cachetype
= CRegStdDWORD(L
"Software\\TortoiseGit\\CacheType", GetSystemMetrics(SM_REMOTESESSION
) ? dll
: exe
, false, HKEY_CURRENT_USER
, KEY_WOW64_64KEY
);
27 onlynonelevated
= CRegStdDWORD(L
"Software\\TortoiseGit\\ShowOverlaysOnlyNonElevated", FALSE
, false, HKEY_CURRENT_USER
, KEY_WOW64_64KEY
);
28 showrecursive
= CRegStdDWORD(L
"Software\\TortoiseGit\\RecursiveOverlay", TRUE
, false, HKEY_CURRENT_USER
, KEY_WOW64_64KEY
);
29 folderoverlay
= CRegStdDWORD(L
"Software\\TortoiseGit\\FolderOverlay", TRUE
, false, HKEY_CURRENT_USER
, KEY_WOW64_64KEY
);
30 driveremote
= CRegStdDWORD(L
"Software\\TortoiseGit\\DriveMaskRemote", FALSE
, false, HKEY_CURRENT_USER
, KEY_WOW64_64KEY
);
31 drivefixed
= CRegStdDWORD(L
"Software\\TortoiseGit\\DriveMaskFixed", TRUE
, false, HKEY_CURRENT_USER
, KEY_WOW64_64KEY
);
32 drivecdrom
= CRegStdDWORD(L
"Software\\TortoiseGit\\DriveMaskCDROM", FALSE
, false, HKEY_CURRENT_USER
, KEY_WOW64_64KEY
);
33 driveremove
= CRegStdDWORD(L
"Software\\TortoiseGit\\DriveMaskRemovable", FALSE
, false, HKEY_CURRENT_USER
, KEY_WOW64_64KEY
);
34 drivefloppy
= CRegStdDWORD(L
"Software\\TortoiseGit\\DriveMaskFloppy", FALSE
, false, HKEY_CURRENT_USER
, KEY_WOW64_64KEY
);
35 driveram
= CRegStdDWORD(L
"Software\\TortoiseGit\\DriveMaskRAM", FALSE
, false, HKEY_CURRENT_USER
, KEY_WOW64_64KEY
);
36 driveunknown
= CRegStdDWORD(L
"Software\\TortoiseGit\\DriveMaskUnknown", FALSE
, false, HKEY_CURRENT_USER
, KEY_WOW64_64KEY
);
37 shellmenuaccelerators
= CRegStdDWORD(L
"Software\\TortoiseGit\\ShellMenuAccelerators", TRUE
, false, HKEY_CURRENT_USER
, KEY_WOW64_64KEY
);
38 simplecontext
= CRegStdDWORD(L
"Software\\TortoiseGit\\SimpleContext", FALSE
, false, HKEY_CURRENT_USER
, KEY_WOW64_64KEY
);
39 unversionedasmodified
= CRegStdDWORD(L
"Software\\TortoiseGit\\UnversionedAsModified", FALSE
, false, HKEY_CURRENT_USER
, KEY_WOW64_64KEY
);
40 recursesubmodules
= CRegStdDWORD(L
"Software\\TortoiseGit\\TGitCacheRecurseSubmodules", FALSE
, false, HKEY_CURRENT_USER
, KEY_WOW64_64KEY
);
41 hidemenusforunversioneditems
= CRegStdDWORD(L
"Software\\TortoiseGit\\HideMenusForUnversionedItems", FALSE
, false, HKEY_CURRENT_USER
, KEY_WOW64_64KEY
);
42 showunversionedoverlay
= CRegStdDWORD(L
"Software\\TortoiseGit\\ShowUnversionedOverlay", TRUE
, false, HKEY_CURRENT_USER
, KEY_WOW64_64KEY
);
43 showignoredoverlay
= CRegStdDWORD(L
"Software\\TortoiseGit\\ShowIgnoredOverlay", TRUE
, false, HKEY_CURRENT_USER
, KEY_WOW64_64KEY
);
44 excludedasnormal
= CRegStdDWORD(L
"Software\\TortoiseGit\\ShowExcludedAsNormal", TRUE
, false, HKEY_CURRENT_USER
, KEY_WOW64_64KEY
);
47 unsigned __int64 entries
= (DEFAULTMENUTOPENTRIES
);
48 menulayoutlow
= CRegStdDWORD(L
"Software\\TortoiseGit\\ContextMenuEntries", entries
& 0xFFFFFFFF, false, HKEY_CURRENT_USER
, KEY_WOW64_64KEY
);
49 menulayouthigh
= CRegStdDWORD(L
"Software\\TortoiseGit\\ContextMenuEntrieshigh", entries
>> 32, false, HKEY_CURRENT_USER
, KEY_WOW64_64KEY
);
51 unsigned __int64 ext
= (DEFAULTMENUEXTENTRIES
);
52 menuextlow
= CRegStdDWORD(L
"Software\\TortoiseGit\\ContextMenuExtEntriesLow", ext
& 0xFFFFFFFF, false, HKEY_CURRENT_USER
, KEY_WOW64_64KEY
);
53 menuexthigh
= CRegStdDWORD(L
"Software\\TortoiseGit\\ContextMenuExtEntriesHigh", ext
>> 32, false, HKEY_CURRENT_USER
, KEY_WOW64_64KEY
);
55 menumasklow_lm
= CRegStdDWORD(L
"Software\\TortoiseGit\\ContextMenuEntriesMaskLow", 0, FALSE
, HKEY_LOCAL_MACHINE
, KEY_WOW64_64KEY
);
56 menumaskhigh_lm
= CRegStdDWORD(L
"Software\\TortoiseGit\\ContextMenuEntriesMaskHigh", 0, FALSE
, HKEY_LOCAL_MACHINE
, KEY_WOW64_64KEY
);
57 menumasklow_cu
= CRegStdDWORD(L
"Software\\TortoiseGit\\ContextMenuEntriesMaskLow", 0, false, HKEY_CURRENT_USER
, KEY_WOW64_64KEY
);
58 menumaskhigh_cu
= CRegStdDWORD(L
"Software\\TortoiseGit\\ContextMenuEntriesMaskHigh", 0, false, HKEY_CURRENT_USER
, KEY_WOW64_64KEY
);
60 langid
= CRegStdDWORD(L
"Software\\TortoiseGit\\LanguageID", 1033, false, HKEY_CURRENT_USER
, KEY_WOW64_64KEY
);
61 blockstatus
= CRegStdDWORD(L
"Software\\TortoiseGit\\BlockStatus", 0, false, HKEY_CURRENT_USER
, KEY_WOW64_64KEY
);
62 std::fill_n(drivetypecache
, 27, (UINT
)-1);
63 if (DWORD(drivefloppy
) == 0)
65 // A: and B: are floppy disks
66 drivetypecache
[0] = DRIVE_REMOVABLE
;
67 drivetypecache
[1] = DRIVE_REMOVABLE
;
69 drivetypepathcache
[0] = L
'\0';
70 nocontextpaths
= CRegStdString(L
"Software\\TortoiseGit\\NoContextPaths", L
"", false, HKEY_CURRENT_USER
, KEY_WOW64_64KEY
);
72 // Use RegNotifyChangeKeyValue() to get a notification event whenever a registry value
73 // below HKCU\Software\TortoiseGit is changed. If a value has changed, re-read all
74 // the registry variables to ensure we use the latest ones
75 RegOpenKeyEx(HKEY_CURRENT_USER
, L
"Software\\TortoiseGit", 0, KEY_NOTIFY
| KEY_WOW64_64KEY
, &m_hNotifyRegKey
);
76 m_registryChangeEvent
= CreateEvent(nullptr, true, false, nullptr);
77 if (RegNotifyChangeKeyValue(m_hNotifyRegKey
, false, REG_NOTIFY_CHANGE_LAST_SET
, m_registryChangeEvent
, TRUE
) != ERROR_SUCCESS
)
79 if (m_registryChangeEvent
)
80 CloseHandle(m_registryChangeEvent
);
81 m_registryChangeEvent
= nullptr;
82 RegCloseKey(m_hNotifyRegKey
);
83 m_hNotifyRegKey
= nullptr;
86 // find out if we're elevated
88 HANDLE hToken
= nullptr;
89 if (::OpenProcessToken(::GetCurrentProcess(), TOKEN_QUERY
, &hToken
))
91 TOKEN_ELEVATION te
= { 0 };
92 DWORD dwReturnLength
= 0;
93 if (::GetTokenInformation(hToken
, TokenElevation
, &te
, sizeof(te
), &dwReturnLength
))
94 isElevated
= (te
.TokenIsElevated
!= 0);
95 ::CloseHandle(hToken
);
99 ShellCache::~ShellCache()
101 if (m_registryChangeEvent
)
102 CloseHandle(m_registryChangeEvent
);
103 m_registryChangeEvent
= nullptr;
105 RegCloseKey(m_hNotifyRegKey
);
106 m_hNotifyRegKey
= nullptr;
109 bool ShellCache::RefreshIfNeeded()
111 // don't wait for the registry change event but only test if such an event
112 // has occurred since the last time we got here.
113 // if the event has occurred, re-read all registry variables and of course
114 // re-set the notification event to get further notifications of registry changes.
115 bool signalled
= WaitForSingleObjectEx(m_registryChangeEvent
, 0, true) != WAIT_TIMEOUT
;
119 if (RegNotifyChangeKeyValue(m_hNotifyRegKey
, false, REG_NOTIFY_CHANGE_LAST_SET
, m_registryChangeEvent
, TRUE
) != ERROR_SUCCESS
)
121 CloseHandle(m_registryChangeEvent
);
122 m_registryChangeEvent
= nullptr;
123 RegCloseKey(m_hNotifyRegKey
);
124 m_hNotifyRegKey
= nullptr;
128 onlynonelevated
.read();
129 showrecursive
.read();
130 folderoverlay
.read();
138 simplecontext
.read();
139 shellmenuaccelerators
.read();
140 unversionedasmodified
.read();
141 recursesubmodules
.read();
142 showunversionedoverlay
.read();
143 showignoredoverlay
.read();
144 excludedasnormal
.read();
145 hidemenusforunversioneditems
.read();
146 menulayoutlow
.read();
147 menulayouthigh
.read();
150 menumasklow_lm
.read();
151 menumaskhigh_lm
.read();
152 menumasklow_cu
.read();
153 menumaskhigh_cu
.read();
156 nocontextpaths
.read();
158 Locker
lock(m_critSec
);
159 pathFilter
.Refresh();
164 ShellCache::CacheType
ShellCache::GetCacheType()
167 return CacheType(DWORD((cachetype
)));
170 DWORD
ShellCache::BlockStatus()
173 return (blockstatus
);
176 unsigned __int64
ShellCache::GetMenuLayout()
179 unsigned __int64 temp
= unsigned __int64(DWORD(menulayouthigh
)) << 32;
180 temp
|= unsigned __int64(DWORD(menulayoutlow
));
184 unsigned __int64
ShellCache::GetMenuExt()
187 unsigned __int64 temp
= unsigned __int64(DWORD(menuexthigh
)) << 32;
188 temp
|= unsigned __int64(DWORD(menuextlow
));
192 unsigned __int64
ShellCache::GetMenuMask()
194 auto ticks
= GetTickCount64();
195 if ((ticks
- menumaskticker
) > ADMINDIRTIMEOUT
)
197 menumaskticker
= ticks
;
198 menumasklow_lm
.read();
199 menumaskhigh_lm
.read();
201 DWORD low
= (DWORD
)menumasklow_lm
| (DWORD
)menumasklow_cu
;
202 DWORD high
= (DWORD
)menumaskhigh_lm
| (DWORD
)menumaskhigh_cu
;
203 unsigned __int64 temp
= unsigned __int64(high
) << 32;
204 temp
|= unsigned __int64(low
);
208 bool ShellCache::IsProcessElevated()
213 BOOL
ShellCache::IsOnlyNonElevated()
216 return (onlynonelevated
);
219 BOOL
ShellCache::IsRecursive()
222 return (showrecursive
);
225 BOOL
ShellCache::IsFolderOverlay()
228 return (folderoverlay
);
231 BOOL
ShellCache::IsSimpleContext()
234 return (simplecontext
!= 0);
237 BOOL
ShellCache::HasShellMenuAccelerators()
240 return (shellmenuaccelerators
!= 0);
243 BOOL
ShellCache::IsUnversionedAsModified()
246 return (unversionedasmodified
);
249 BOOL
ShellCache::IsRecurseSubmodules()
252 return (recursesubmodules
);
255 BOOL
ShellCache::ShowUnversionedOverlay()
258 return (showunversionedoverlay
);
261 BOOL
ShellCache::ShowIgnoredOverlay()
264 return (showignoredoverlay
);
267 BOOL
ShellCache::ShowExcludedAsNormal()
270 return (excludedasnormal
);
273 BOOL
ShellCache::HideMenusForUnversionedItems()
276 return (hidemenusforunversioneditems
);
279 BOOL
ShellCache::IsRemote()
282 return (driveremote
);
285 BOOL
ShellCache::IsFixed()
291 BOOL
ShellCache::IsCDRom()
297 BOOL
ShellCache::IsRemovable()
300 return (driveremove
);
303 BOOL
ShellCache::IsRAM()
309 BOOL
ShellCache::IsUnknown()
312 return (driveunknown
);
315 BOOL
ShellCache::IsContextPathAllowed(LPCTSTR path
)
317 Locker
lock(m_critSec
);
318 ExcludeContextValid();
319 for (const auto& exPath
: excontextvector
)
323 if (exPath
[exPath
.size() - 1] == '*')
325 tstring str
= exPath
.substr(0, exPath
.size() - 1);
326 if (_wcsnicmp(str
.c_str(), path
, str
.size()) == 0)
329 else if (_wcsicmp(exPath
.c_str(), path
) == 0)
335 BOOL
ShellCache::IsPathAllowed(LPCTSTR path
)
338 Locker
lock(m_critSec
);
339 tristate_t allowed
= pathFilter
.IsPathAllowed(path
);
340 if (allowed
!= tristate_unknown
)
341 return allowed
== tristate_true
? TRUE
: FALSE
;
344 int drivenumber
= PathGetDriveNumber(path
);
345 if ((drivenumber
>= 0) && (drivenumber
< 25))
347 drivetype
= drivetypecache
[drivenumber
];
348 if ((drivetype
== -1) || ((GetTickCount64() - drivetypeticker
) > DRIVETYPETIMEOUT
))
350 if ((DWORD(drivefloppy
) == 0) && ((drivenumber
== 0) || (drivenumber
== 1)))
351 drivetypecache
[drivenumber
] = DRIVE_REMOVABLE
;
354 drivetypeticker
= GetTickCount64();
355 TCHAR pathbuf
[MAX_PATH
+ 4] = { 0 }; // MAX_PATH ok here. PathStripToRoot works with partial paths too.
356 wcsncpy_s(pathbuf
, path
, _countof(pathbuf
) - 1);
357 PathStripToRoot(pathbuf
);
358 PathAddBackslash(pathbuf
);
359 CTraceToOutputDebugString::Instance()(_T(__FUNCTION__
) L
": GetDriveType for %s, Drive %d\n", pathbuf
, drivenumber
);
360 drivetype
= GetDriveType(pathbuf
);
361 drivetypecache
[drivenumber
] = drivetype
;
367 TCHAR pathbuf
[MAX_PATH
+ 4] = { 0 }; // MAX_PATH ok here. PathIsUNCServer works with partial paths too.
368 wcsncpy_s(pathbuf
, path
, _countof(pathbuf
) - 1);
369 if (PathIsUNCServer(pathbuf
))
370 drivetype
= DRIVE_REMOTE
;
373 PathStripToRoot(pathbuf
);
374 PathAddBackslash(pathbuf
);
375 if (wcsncmp(pathbuf
, drivetypepathcache
, MAX_PATH
- 1) == 0) // MAX_PATH ok.
376 drivetype
= drivetypecache
[26];
379 CTraceToOutputDebugString::Instance()(_T(__FUNCTION__
) L
"GetDriveType for %s\n", pathbuf
);
380 drivetype
= GetDriveType(pathbuf
);
381 drivetypecache
[26] = drivetype
;
382 wcsncpy_s(drivetypepathcache
, pathbuf
, MAX_PATH
- 1); // MAX_PATH ok.
386 if ((drivetype
== DRIVE_REMOVABLE
) && (!IsRemovable()))
388 if ((drivetype
== DRIVE_FIXED
) && (!IsFixed()))
390 if (((drivetype
== DRIVE_REMOTE
) || (drivetype
== DRIVE_NO_ROOT_DIR
)) && (!IsRemote()))
392 if ((drivetype
== DRIVE_CDROM
) && (!IsCDRom()))
394 if ((drivetype
== DRIVE_RAMDISK
) && (!IsRAM()))
396 if ((drivetype
== DRIVE_UNKNOWN
) && (IsUnknown()))
402 DWORD
ShellCache::GetLangID()
408 BOOL
ShellCache::HasGITAdminDir(LPCTSTR path
, BOOL bIsDir
, CString
* ProjectTopDir
/*= nullptr*/)
410 tstring
folder(path
);
413 size_t pos
= folder
.rfind(L
'\\');
414 if (pos
!= tstring::npos
)
417 std::map
<tstring
, AdminDir_s
>::const_iterator iter
;
418 if ((iter
= admindircache
.find(folder
)) != admindircache
.cend())
420 Locker
lock(m_critSec
);
421 if ((GetTickCount64() - iter
->second
.timeout
) < ADMINDIRTIMEOUT
)
423 if (ProjectTopDir
&& iter
->second
.bHasAdminDir
)
424 *ProjectTopDir
= iter
->second
.sProjectRoot
.c_str();
425 return iter
->second
.bHasAdminDir
;
429 CString sProjectRoot
;
430 BOOL hasAdminDir
= GitAdminDir::HasAdminDir(folder
.c_str(), true, &sProjectRoot
);
432 Locker
lock(m_critSec
);
433 AdminDir_s
& ad
= admindircache
[folder
];
434 ad
.bHasAdminDir
= hasAdminDir
;
435 ad
.timeout
= GetTickCount64();
438 ad
.sProjectRoot
.assign(sProjectRoot
);
440 *ProjectTopDir
= sProjectRoot
;
446 void ShellCache::ExcludeContextValid()
448 if (RefreshIfNeeded())
450 Locker
lock(m_critSec
);
451 if (excludecontextstr
.compare((tstring
)nocontextpaths
) == 0)
453 excludecontextstr
= (tstring
)nocontextpaths
;
454 excontextvector
.clear();
455 size_t pos
= 0, pos_ant
= 0;
456 pos
= excludecontextstr
.find(L
'\n', pos_ant
);
457 while (pos
!= tstring::npos
)
459 tstring token
= excludecontextstr
.substr(pos_ant
, pos
- pos_ant
);
460 excontextvector
.push_back(token
);
462 pos
= excludecontextstr
.find(L
'\n', pos_ant
);
464 if (!excludecontextstr
.empty())
465 excontextvector
.push_back(excludecontextstr
.substr(pos_ant
, excludecontextstr
.size() - 1));
466 excludecontextstr
= (tstring
)nocontextpaths
;
470 // construct \ref data content
471 void ShellCache::CPathFilter::AddEntry(const tstring
& s
, bool include
)
473 static wchar_t pathbuf
[MAX_PATH
* 4] = { 0 };
477 TCHAR lastChar
= *s
.rbegin();
480 entry
.hasSubFolderEntries
= false;
481 entry
.recursive
= lastChar
!= L
'?';
482 entry
.included
= include
? tristate_true
: tristate_false
;
483 entry
.subPathIncluded
= include
== entry
.recursive
? tristate_true
: tristate_false
;
486 if ((lastChar
== L
'?') || (lastChar
== L
'*'))
487 entry
.path
.erase(s
.length() - 1);
488 if (!entry
.path
.empty() && (*entry
.path
.rbegin() == L
'\\'))
489 entry
.path
.erase(entry
.path
.length() - 1);
491 auto ret
= ExpandEnvironmentStrings(entry
.path
.c_str(), pathbuf
, _countof(pathbuf
));
492 if ((ret
> 0) && (ret
< _countof(pathbuf
)))
493 entry
.path
= pathbuf
;
495 data
.push_back(entry
);
498 void ShellCache::CPathFilter::AddEntries(const tstring
& s
, bool include
)
500 size_t pos
= 0, pos_ant
= 0;
501 pos
= s
.find(L
'\n', pos_ant
);
502 while (pos
!= tstring::npos
)
504 AddEntry(s
.substr(pos_ant
, pos
- pos_ant
), include
);
506 pos
= s
.find(L
'\n', pos_ant
);
510 AddEntry(s
.substr(pos_ant
, s
.size() - 1), include
);
513 // for all paths, have at least one entry in data
514 void ShellCache::CPathFilter::PostProcessData()
519 std::sort(data
.begin(), data
.end());
521 // update subPathIncluded props and remove duplicate entries
522 auto begin
= data
.begin();
523 auto end
= data
.end();
525 for (auto source
= begin
; source
!= end
; ++source
)
527 if (_wcsicmp(source
->path
.c_str(), dest
->path
.c_str()) == 0)
529 // multiple entries for the same path -> merge them
531 // update subPathIncluded
532 // (all relevant parent info has already been normalized)
533 if (!source
->recursive
)
534 source
->subPathIncluded
= IsPathAllowed(source
->path
.c_str(), begin
, dest
);
536 // multiple specs for the same path
537 // -> merge them into the existing entry @ dest
538 if (!source
->recursive
&& dest
->recursive
)
540 // reset the marker for the this case
541 dest
->recursive
= false;
542 dest
->included
= source
->included
;
546 // include beats exclude
547 if (source
->included
== tristate_true
)
548 dest
->included
= tristate_true
;
549 if (source
->recursive
&& source
->subPathIncluded
== tristate_true
)
550 dest
->subPathIncluded
= tristate_true
;
555 // new path -> don't merge this entry
556 size_t destSize
= dest
->path
.size();
557 dest
->hasSubFolderEntries
= (source
->path
.size() > destSize
) && (source
->path
[destSize
] == L
'\\') && (_wcsnicmp(source
->path
.substr(0, destSize
).c_str(), dest
->path
.c_str(), destSize
) == 0);
561 // update subPathIncluded
562 // (all relevant parent info has already been normalized)
563 if (!dest
->recursive
)
564 dest
->subPathIncluded
= IsPathAllowed(source
->path
.c_str(), begin
, dest
);
568 // remove duplicate info
570 data
.erase(++dest
, end
);
573 // lookup. default result is "unknown".
574 // We must look for *every* parent path because of situations like:
575 // excluded: C:, C:\some\deep\path
577 // lookup for C:\some\deeper\path
578 tristate_t
ShellCache::CPathFilter::IsPathAllowed(LPCTSTR path
, TData::const_iterator begin
, TData::const_iterator end
) const
580 tristate_t result
= tristate_unknown
;
582 // handle special cases
586 size_t maxLength
= wcslen(path
);
590 // look for the most specific entry, start at the root
594 LPCTSTR backslash
= wcschr(path
+ pos
+ 1,L
'\\');
595 pos
= backslash
== nullptr ? maxLength
: backslash
- path
;
597 std::pair
<LPCTSTR
, size_t> toFind(path
, pos
);
598 TData::const_iterator iter
= std::lower_bound(begin
, end
, toFind
);
600 // found a relevant entry?
601 if ((iter
!= end
) && (iter
->path
.length() == pos
) && (_wcsnicmp(iter
->path
.c_str(), path
, pos
) == 0))
604 if (pos
== maxLength
)
605 return iter
->included
;
608 result
= iter
->subPathIncluded
;
611 if (iter
->hasSubFolderEntries
)
618 // set a (potentially) closer lower limit
623 // set a (potentially) closer upper limit
624 end
= std::upper_bound(begin
, end
, toFind
);
625 } while ((pos
< maxLength
) && (begin
!= end
));
627 // nothing more specific found
633 ShellCache::CPathFilter::CPathFilter()
634 : excludelist(L
"Software\\TortoiseGit\\OverlayExcludeList", L
"", false, HKEY_CURRENT_USER
, KEY_WOW64_64KEY
)
635 , includelist(L
"Software\\TortoiseGit\\OverlayIncludeList", L
"", false, HKEY_CURRENT_USER
, KEY_WOW64_64KEY
)
640 // notify of (potential) registry settings
642 void ShellCache::CPathFilter::Refresh()
647 if ((excludeliststr
.compare((tstring
)excludelist
) == 0) && (includeliststr
.compare((tstring
)includelist
) == 0))
650 excludeliststr
= (tstring
)excludelist
;
651 includeliststr
= (tstring
)includelist
;
653 AddEntries(excludeliststr
, false);
654 AddEntries(includeliststr
, true);
660 tristate_t
ShellCache::CPathFilter::IsPathAllowed(LPCTSTR path
) const
663 return tristate_unknown
;
664 // always ignore the recycle bin
665 PTSTR pFound
= StrStrI(path
, L
":\\RECYCLER");
668 if ((*(pFound
+ 10) == L
'\0') || (*(pFound
+ 10) == L
'\\'))
669 return tristate_false
;
671 pFound
= StrStrI(path
, L
":\\$Recycle.Bin");
674 if ((*(pFound
+ 14) == '\0') || (*(pFound
+ 14) == L
'\\'))
675 return tristate_false
;
677 return IsPathAllowed(path
, data
.begin(), data
.end());