1 // TortoiseGit - a Windows shell extension for easy version control
3 // Copyright (C) 2012-2016 - TortoiseGit
4 // Copyright (C) 2003-2016 - 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 showrecursive
= CRegStdDWORD(L
"Software\\TortoiseGit\\RecursiveOverlay", TRUE
, false, HKEY_CURRENT_USER
, KEY_WOW64_64KEY
);
28 folderoverlay
= CRegStdDWORD(L
"Software\\TortoiseGit\\FolderOverlay", TRUE
, false, HKEY_CURRENT_USER
, KEY_WOW64_64KEY
);
29 driveremote
= CRegStdDWORD(L
"Software\\TortoiseGit\\DriveMaskRemote", FALSE
, false, HKEY_CURRENT_USER
, KEY_WOW64_64KEY
);
30 drivefixed
= CRegStdDWORD(L
"Software\\TortoiseGit\\DriveMaskFixed", TRUE
, false, HKEY_CURRENT_USER
, KEY_WOW64_64KEY
);
31 drivecdrom
= CRegStdDWORD(L
"Software\\TortoiseGit\\DriveMaskCDROM", FALSE
, false, HKEY_CURRENT_USER
, KEY_WOW64_64KEY
);
32 driveremove
= CRegStdDWORD(L
"Software\\TortoiseGit\\DriveMaskRemovable", FALSE
, false, HKEY_CURRENT_USER
, KEY_WOW64_64KEY
);
33 drivefloppy
= CRegStdDWORD(L
"Software\\TortoiseGit\\DriveMaskFloppy", FALSE
, false, HKEY_CURRENT_USER
, KEY_WOW64_64KEY
);
34 driveram
= CRegStdDWORD(L
"Software\\TortoiseGit\\DriveMaskRAM", FALSE
, false, HKEY_CURRENT_USER
, KEY_WOW64_64KEY
);
35 driveunknown
= CRegStdDWORD(L
"Software\\TortoiseGit\\DriveMaskUnknown", FALSE
, false, HKEY_CURRENT_USER
, KEY_WOW64_64KEY
);
36 shellmenuaccelerators
= CRegStdDWORD(L
"Software\\TortoiseGit\\ShellMenuAccelerators", TRUE
, false, HKEY_CURRENT_USER
, KEY_WOW64_64KEY
);
37 simplecontext
= CRegStdDWORD(L
"Software\\TortoiseGit\\SimpleContext", FALSE
, false, HKEY_CURRENT_USER
, KEY_WOW64_64KEY
);
38 unversionedasmodified
= CRegStdDWORD(L
"Software\\TortoiseGit\\UnversionedAsModified", FALSE
, false, HKEY_CURRENT_USER
, KEY_WOW64_64KEY
);
39 recursesubmodules
= CRegStdDWORD(L
"Software\\TortoiseGit\\TGitCacheRecurseSubmodules", FALSE
, false, HKEY_CURRENT_USER
, KEY_WOW64_64KEY
);
40 hidemenusforunversioneditems
= CRegStdDWORD(L
"Software\\TortoiseGit\\HideMenusForUnversionedItems", FALSE
, false, HKEY_CURRENT_USER
, KEY_WOW64_64KEY
);
41 showunversionedoverlay
= CRegStdDWORD(L
"Software\\TortoiseGit\\ShowUnversionedOverlay", TRUE
, false, HKEY_CURRENT_USER
, KEY_WOW64_64KEY
);
42 showignoredoverlay
= CRegStdDWORD(L
"Software\\TortoiseGit\\ShowIgnoredOverlay", TRUE
, false, HKEY_CURRENT_USER
, KEY_WOW64_64KEY
);
43 getlocktop
= CRegStdDWORD(L
"Software\\TortoiseGit\\GetLockTop", 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 CloseHandle(m_registryChangeEvent
);
80 m_registryChangeEvent
= nullptr;
81 RegCloseKey(m_hNotifyRegKey
);
82 m_hNotifyRegKey
= nullptr;
86 ShellCache::~ShellCache()
88 if (m_registryChangeEvent
)
89 CloseHandle(m_registryChangeEvent
);
90 m_registryChangeEvent
= nullptr;
92 RegCloseKey(m_hNotifyRegKey
);
93 m_hNotifyRegKey
= nullptr;
96 bool ShellCache::RefreshIfNeeded()
98 // don't wait for the registry change event but only test if such an event
99 // has occurred since the last time we got here.
100 // if the event has occurred, re-read all registry variables and of course
101 // re-set the notification event to get further notifications of registry changes.
102 bool signalled
= WaitForSingleObjectEx(m_registryChangeEvent
, 0, true) != WAIT_TIMEOUT
;
106 if (RegNotifyChangeKeyValue(m_hNotifyRegKey
, false, REG_NOTIFY_CHANGE_LAST_SET
, m_registryChangeEvent
, TRUE
) != ERROR_SUCCESS
)
108 CloseHandle(m_registryChangeEvent
);
109 m_registryChangeEvent
= nullptr;
110 RegCloseKey(m_hNotifyRegKey
);
111 m_hNotifyRegKey
= nullptr;
115 showrecursive
.read();
116 folderoverlay
.read();
124 simplecontext
.read();
125 shellmenuaccelerators
.read();
126 unversionedasmodified
.read();
127 recursesubmodules
.read();
128 showunversionedoverlay
.read();
129 showignoredoverlay
.read();
130 excludedasnormal
.read();
131 hidemenusforunversioneditems
.read();
132 menulayoutlow
.read();
133 menulayouthigh
.read();
137 menumasklow_lm
.read();
138 menumaskhigh_lm
.read();
139 menumasklow_cu
.read();
140 menumaskhigh_cu
.read();
141 nocontextpaths
.read();
143 Locker
lock(m_critSec
);
144 pathFilter
.Refresh();
149 ShellCache::CacheType
ShellCache::GetCacheType()
152 return CacheType(DWORD((cachetype
)));
155 DWORD
ShellCache::BlockStatus()
158 return (blockstatus
);
161 unsigned __int64
ShellCache::GetMenuLayout()
164 unsigned __int64 temp
= unsigned __int64(DWORD(menulayouthigh
)) << 32;
165 temp
|= unsigned __int64(DWORD(menulayoutlow
));
169 unsigned __int64
ShellCache::GetMenuExt()
172 unsigned __int64 temp
= unsigned __int64(DWORD(menuexthigh
)) << 32;
173 temp
|= unsigned __int64(DWORD(menuextlow
));
177 unsigned __int64
ShellCache::GetMenuMask()
179 auto ticks
= GetTickCount64();
180 if ((ticks
- menumaskticker
) > ADMINDIRTIMEOUT
)
182 menumaskticker
= ticks
;
183 menumasklow_lm
.read();
184 menumaskhigh_lm
.read();
186 DWORD low
= (DWORD
)menumasklow_lm
| (DWORD
)menumasklow_cu
;
187 DWORD high
= (DWORD
)menumaskhigh_lm
| (DWORD
)menumaskhigh_cu
;
188 unsigned __int64 temp
= unsigned __int64(high
) << 32;
189 temp
|= unsigned __int64(low
);
193 BOOL
ShellCache::IsRecursive()
196 return (showrecursive
);
199 BOOL
ShellCache::IsFolderOverlay()
202 return (folderoverlay
);
205 BOOL
ShellCache::IsSimpleContext()
208 return (simplecontext
!= 0);
211 BOOL
ShellCache::HasShellMenuAccelerators()
214 return (shellmenuaccelerators
!= 0);
217 BOOL
ShellCache::IsUnversionedAsModified()
220 return (unversionedasmodified
);
223 BOOL
ShellCache::IsRecurseSubmodules()
226 return (recursesubmodules
);
229 BOOL
ShellCache::ShowUnversionedOverlay()
232 return (showunversionedoverlay
);
235 BOOL
ShellCache::ShowIgnoredOverlay()
238 return (showignoredoverlay
);
241 BOOL
ShellCache::IsGetLockTop()
247 BOOL
ShellCache::ShowExcludedAsNormal()
250 return (excludedasnormal
);
253 BOOL
ShellCache::HideMenusForUnversionedItems()
256 return (hidemenusforunversioneditems
);
259 BOOL
ShellCache::IsRemote()
262 return (driveremote
);
265 BOOL
ShellCache::IsFixed()
271 BOOL
ShellCache::IsCDRom()
277 BOOL
ShellCache::IsRemovable()
280 return (driveremove
);
283 BOOL
ShellCache::IsRAM()
289 BOOL
ShellCache::IsUnknown()
292 return (driveunknown
);
295 BOOL
ShellCache::IsContextPathAllowed(LPCTSTR path
)
297 Locker
lock(m_critSec
);
298 ExcludeContextValid();
299 for (const auto& exPath
: excontextvector
)
303 if (exPath
.at(exPath
.size() - 1) == '*')
305 tstring str
= exPath
.substr(0, exPath
.size() - 1);
306 if (_wcsnicmp(str
.c_str(), path
, str
.size()) == 0)
309 else if (_wcsicmp(exPath
.c_str(), path
) == 0)
315 BOOL
ShellCache::IsPathAllowed(LPCTSTR path
)
317 ValidatePathFilter();
318 Locker
lock(m_critSec
);
319 tristate_t allowed
= pathFilter
.IsPathAllowed(path
);
320 if (allowed
!= tristate_unknown
)
321 return allowed
== tristate_true
? TRUE
: FALSE
;
324 int drivenumber
= PathGetDriveNumber(path
);
325 if ((drivenumber
>= 0) && (drivenumber
< 25))
327 drivetype
= drivetypecache
[drivenumber
];
328 if ((drivetype
== -1) || ((GetTickCount64() - drivetypeticker
) > DRIVETYPETIMEOUT
))
330 if ((DWORD(drivefloppy
) == 0) && ((drivenumber
== 0) || (drivenumber
== 1)))
331 drivetypecache
[drivenumber
] = DRIVE_REMOVABLE
;
334 drivetypeticker
= GetTickCount64();
335 TCHAR pathbuf
[MAX_PATH
+ 4] = { 0 }; // MAX_PATH ok here. PathStripToRoot works with partial paths too.
336 wcsncpy_s(pathbuf
, path
, _countof(pathbuf
) - 1);
337 PathStripToRoot(pathbuf
);
338 PathAddBackslash(pathbuf
);
339 CTraceToOutputDebugString::Instance()(_T(__FUNCTION__
) L
": GetDriveType for %s, Drive %d\n", pathbuf
, drivenumber
);
340 drivetype
= GetDriveType(pathbuf
);
341 drivetypecache
[drivenumber
] = drivetype
;
347 TCHAR pathbuf
[MAX_PATH
+ 4] = { 0 }; // MAX_PATH ok here. PathIsUNCServer works with partial paths too.
348 wcsncpy_s(pathbuf
, path
, _countof(pathbuf
) - 1);
349 if (PathIsUNCServer(pathbuf
))
350 drivetype
= DRIVE_REMOTE
;
353 PathStripToRoot(pathbuf
);
354 PathAddBackslash(pathbuf
);
355 if (wcsncmp(pathbuf
, drivetypepathcache
, MAX_PATH
- 1) == 0) // MAX_PATH ok.
356 drivetype
= drivetypecache
[26];
359 CTraceToOutputDebugString::Instance()(_T(__FUNCTION__
) L
"GetDriveType for %s\n", pathbuf
);
360 drivetype
= GetDriveType(pathbuf
);
361 drivetypecache
[26] = drivetype
;
362 wcsncpy_s(drivetypepathcache
, pathbuf
, MAX_PATH
- 1); // MAX_PATH ok.
366 if ((drivetype
== DRIVE_REMOVABLE
) && (!IsRemovable()))
368 if ((drivetype
== DRIVE_FIXED
) && (!IsFixed()))
370 if (((drivetype
== DRIVE_REMOTE
) || (drivetype
== DRIVE_NO_ROOT_DIR
)) && (!IsRemote()))
372 if ((drivetype
== DRIVE_CDROM
) && (!IsCDRom()))
374 if ((drivetype
== DRIVE_RAMDISK
) && (!IsRAM()))
376 if ((drivetype
== DRIVE_UNKNOWN
) && (IsUnknown()))
382 DWORD
ShellCache::GetLangID()
388 BOOL
ShellCache::HasGITAdminDir(LPCTSTR path
, BOOL bIsDir
, CString
* ProjectTopDir
/*= nullptr*/)
390 tstring
folder(path
);
393 size_t pos
= folder
.rfind(L
'\\');
394 if (pos
!= tstring::npos
)
397 std::map
<tstring
, AdminDir_s
>::const_iterator iter
;
398 if ((iter
= admindircache
.find(folder
)) != admindircache
.cend())
400 Locker
lock(m_critSec
);
401 if ((GetTickCount64() - iter
->second
.timeout
) < ADMINDIRTIMEOUT
)
403 if (ProjectTopDir
&& iter
->second
.bHasAdminDir
)
404 *ProjectTopDir
= iter
->second
.sProjectRoot
.c_str();
405 return iter
->second
.bHasAdminDir
;
409 CString sProjectRoot
;
410 BOOL hasAdminDir
= GitAdminDir::HasAdminDir(folder
.c_str(), true, &sProjectRoot
);
412 Locker
lock(m_critSec
);
413 AdminDir_s
& ad
= admindircache
[folder
];
414 ad
.bHasAdminDir
= hasAdminDir
;
415 ad
.timeout
= GetTickCount64();
418 ad
.sProjectRoot
.assign(sProjectRoot
);
420 *ProjectTopDir
= sProjectRoot
;
426 void ShellCache::ExcludeContextValid()
428 if (RefreshIfNeeded())
430 Locker
lock(m_critSec
);
431 if (excludecontextstr
.compare((tstring
)nocontextpaths
) == 0)
433 excludecontextstr
= (tstring
)nocontextpaths
;
434 excontextvector
.clear();
435 size_t pos
= 0, pos_ant
= 0;
436 pos
= excludecontextstr
.find(L
'\n', pos_ant
);
437 while (pos
!= tstring::npos
)
439 tstring token
= excludecontextstr
.substr(pos_ant
, pos
- pos_ant
);
440 excontextvector
.push_back(token
);
442 pos
= excludecontextstr
.find(L
'\n', pos_ant
);
444 if (!excludecontextstr
.empty())
445 excontextvector
.push_back(excludecontextstr
.substr(pos_ant
, excludecontextstr
.size() - 1));
446 excludecontextstr
= (tstring
)nocontextpaths
;
450 void ShellCache::ValidatePathFilter()
452 if (RefreshIfNeeded())
454 Locker
lock(m_critSec
);
455 pathFilter
.Refresh();
459 // construct \ref data content
460 void ShellCache::CPathFilter::AddEntry(const tstring
& s
, bool include
)
462 static wchar_t pathbuf
[MAX_PATH
* 4] = { 0 };
466 TCHAR lastChar
= *s
.rbegin();
469 entry
.hasSubFolderEntries
= false;
470 entry
.recursive
= lastChar
!= L
'?';
471 entry
.included
= include
? tristate_true
: tristate_false
;
472 entry
.subPathIncluded
= include
== entry
.recursive
? tristate_true
: tristate_false
;
475 if ((lastChar
== L
'?') || (lastChar
== L
'*'))
476 entry
.path
.erase(s
.length() - 1);
477 if (!entry
.path
.empty() && (*entry
.path
.rbegin() == L
'\\'))
478 entry
.path
.erase(entry
.path
.length() - 1);
480 auto ret
= ExpandEnvironmentStrings(entry
.path
.c_str(), pathbuf
, _countof(pathbuf
));
481 if ((ret
> 0) && (ret
< _countof(pathbuf
)))
482 entry
.path
= pathbuf
;
484 data
.push_back(entry
);
487 void ShellCache::CPathFilter::AddEntries(const tstring
& s
, bool include
)
489 size_t pos
= 0, pos_ant
= 0;
490 pos
= s
.find(L
'\n', pos_ant
);
491 while (pos
!= tstring::npos
)
493 AddEntry(s
.substr(pos_ant
, pos
- pos_ant
), include
);
495 pos
= s
.find(L
'\n', pos_ant
);
499 AddEntry(s
.substr(pos_ant
, s
.size() - 1), include
);
502 // for all paths, have at least one entry in data
503 void ShellCache::CPathFilter::PostProcessData()
508 std::sort(data
.begin(), data
.end());
510 // update subPathIncluded props and remove duplicate entries
511 auto begin
= data
.begin();
512 auto end
= data
.end();
514 for (auto source
= begin
; source
!= end
; ++source
)
516 if (_wcsicmp(source
->path
.c_str(), dest
->path
.c_str()) == 0)
518 // multiple entries for the same path -> merge them
520 // update subPathIncluded
521 // (all relevant parent info has already been normalized)
522 if (!source
->recursive
)
523 source
->subPathIncluded
= IsPathAllowed(source
->path
.c_str(), begin
, dest
);
525 // multiple specs for the same path
526 // -> merge them into the existing entry @ dest
527 if (!source
->recursive
&& dest
->recursive
)
529 // reset the marker for the this case
530 dest
->recursive
= false;
531 dest
->included
= source
->included
;
535 // include beats exclude
536 if (source
->included
== tristate_true
)
537 dest
->included
= tristate_true
;
538 if (source
->recursive
&& source
->subPathIncluded
== tristate_true
)
539 dest
->subPathIncluded
= tristate_true
;
544 // new path -> don't merge this entry
545 size_t destSize
= dest
->path
.size();
546 dest
->hasSubFolderEntries
= (source
->path
.size() > destSize
) && (source
->path
[destSize
] == L
'\\') && (_wcsnicmp(source
->path
.substr(0, destSize
).c_str(), dest
->path
.c_str(), destSize
) == 0);
550 // update subPathIncluded
551 // (all relevant parent info has already been normalized)
552 if (!dest
->recursive
)
553 dest
->subPathIncluded
= IsPathAllowed(source
->path
.c_str(), begin
, dest
);
557 // remove duplicate info
559 data
.erase(++dest
, end
);
562 // lookup. default result is "unknown".
563 // We must look for *every* parent path because of situations like:
564 // excluded: C:, C:\some\deep\path
566 // lookup for C:\some\deeper\path
567 tristate_t
ShellCache::CPathFilter::IsPathAllowed(LPCTSTR path
, TData::const_iterator begin
, TData::const_iterator end
) const
569 tristate_t result
= tristate_unknown
;
571 // handle special cases
575 size_t maxLength
= wcslen(path
);
579 // look for the most specific entry, start at the root
583 LPCTSTR backslash
= wcschr(path
+ pos
+ 1,L
'\\');
584 pos
= backslash
== nullptr ? maxLength
: backslash
- path
;
586 std::pair
<LPCTSTR
, size_t> toFind(path
, pos
);
587 TData::const_iterator iter
= std::lower_bound(begin
, end
, toFind
);
589 // found a relevant entry?
590 if ((iter
!= end
) && (iter
->path
.length() == pos
) && (_wcsnicmp(iter
->path
.c_str(), path
, pos
) == 0))
593 if (pos
== maxLength
)
594 return iter
->included
;
597 result
= iter
->subPathIncluded
;
600 if (iter
->hasSubFolderEntries
)
607 // set a (potentially) closer lower limit
612 // set a (potentially) closer upper limit
613 end
= std::upper_bound(begin
, end
, toFind
);
614 } while ((pos
< maxLength
) && (begin
!= end
));
616 // nothing more specific found
622 ShellCache::CPathFilter::CPathFilter()
623 : excludelist(L
"Software\\TortoiseGit\\OverlayExcludeList", L
"", false, HKEY_CURRENT_USER
, KEY_WOW64_64KEY
)
624 , includelist(L
"Software\\TortoiseGit\\OverlayIncludeList", L
"", false, HKEY_CURRENT_USER
, KEY_WOW64_64KEY
)
629 // notify of (potential) registry settings
631 void ShellCache::CPathFilter::Refresh()
636 if ((excludeliststr
.compare((tstring
)excludelist
) == 0) && (includeliststr
.compare((tstring
)includelist
) == 0))
639 excludeliststr
= (tstring
)excludelist
;
640 includeliststr
= (tstring
)includelist
;
642 AddEntries(excludeliststr
, false);
643 AddEntries(includeliststr
, true);
649 tristate_t
ShellCache::CPathFilter::IsPathAllowed(LPCTSTR path
) const
652 return tristate_unknown
;
653 // always ignore the recycle bin
654 PTSTR pFound
= StrStrI(path
, L
":\\RECYCLER");
657 if ((*(pFound
+ 10) == L
'\0') || (*(pFound
+ 10) == L
'\\'))
658 return tristate_false
;
660 pFound
= StrStrI(path
, L
":\\$Recycle.Bin");
663 if ((*(pFound
+ 14) == '\0') || (*(pFound
+ 14) == L
'\\'))
664 return tristate_false
;
666 return IsPathAllowed(path
, data
.begin(), data
.end());