1 // TortoiseGit - a Windows shell extension for easy version control
3 // Copyright (C) 2003-2008 - Stefan Kueng
5 // This program is free software; you can redistribute it and/or
6 // modify it under the terms of the GNU General Public License
7 // as published by the Free Software Foundation; either version 2
8 // of the License, or (at your option) any later version.
10 // This program is distributed in the hope that it will be useful,
11 // but WITHOUT ANY WARRANTY; without even the implied warranty of
12 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 // GNU General Public License for more details.
15 // You should have received a copy of the GNU General Public License
16 // along with this program; if not, write to the Free Software Foundation,
17 // 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
22 #include "GitAdminDir.h"
24 #define REGISTRYTIMEOUT 2000
25 #define EXCLUDELISTTIMEOUT 5000
26 #define ADMINDIRTIMEOUT 10000
27 #define DRIVETYPETIMEOUT 300000 // 5 min
28 #define NUMBERFMTTIMEOUT 300000
29 #define MENUTIMEOUT 100
31 typedef CComCritSecLock
<CComCriticalSection
> Locker
;
34 * \ingroup TortoiseShell
35 * Helper class which caches access to the registry. Also provides helper methods
36 * for checks against the settings stored in the registry.
49 cachetype
= CRegStdWORD(_T("Software\\TortoiseGit\\CacheType"), GetSystemMetrics(SM_REMOTESESSION
) ? dll
: exe
);
50 showrecursive
= CRegStdWORD(_T("Software\\TortoiseGit\\RecursiveOverlay"), TRUE
);
51 folderoverlay
= CRegStdWORD(_T("Software\\TortoiseGit\\FolderOverlay"), TRUE
);
52 driveremote
= CRegStdWORD(_T("Software\\TortoiseGit\\DriveMaskRemote"));
53 drivefixed
= CRegStdWORD(_T("Software\\TortoiseGit\\DriveMaskFixed"), TRUE
);
54 drivecdrom
= CRegStdWORD(_T("Software\\TortoiseGit\\DriveMaskCDROM"));
55 driveremove
= CRegStdWORD(_T("Software\\TortoiseGit\\DriveMaskRemovable"));
56 drivefloppy
= CRegStdWORD(_T("Software\\TortoiseGit\\DriveMaskFloppy"));
57 driveram
= CRegStdWORD(_T("Software\\TortoiseGit\\DriveMaskRAM"));
58 driveunknown
= CRegStdWORD(_T("Software\\TortoiseGit\\DriveMaskUnknown"));
59 excludelist
= CRegStdString(_T("Software\\TortoiseGit\\OverlayExcludeList"));
60 includelist
= CRegStdString(_T("Software\\TortoiseGit\\OverlayIncludeList"));
61 simplecontext
= CRegStdWORD(_T("Software\\TortoiseGit\\SimpleContext"), FALSE
);
62 unversionedasmodified
= CRegStdWORD(_T("Software\\TortoiseGit\\UnversionedAsModified"), FALSE
);
63 showunversionedoverlay
= CRegStdWORD(_T("Software\\TortoiseGit\\ShowUnversionedOverlay"), TRUE
);
64 showignoredoverlay
= CRegStdWORD(_T("Software\\TortoiseGit\\ShowIgnoredOverlay"), TRUE
);
65 getlocktop
= CRegStdWORD(_T("Software\\TortoiseGit\\GetLockTop"), TRUE
);
66 excludedasnormal
= CRegStdWORD(_T("Software\\TortoiseGit\\ShowExcludedAsNormal"), TRUE
);
67 cachetypeticker
= GetTickCount();
68 recursiveticker
= cachetypeticker
;
69 folderoverlayticker
= cachetypeticker
;
70 driveticker
= cachetypeticker
;
71 drivetypeticker
= cachetypeticker
;
72 langticker
= cachetypeticker
;
73 columnrevformatticker
= cachetypeticker
;
74 excludelistticker
= cachetypeticker
;
75 includelistticker
= cachetypeticker
;
76 simplecontextticker
= cachetypeticker
;
77 unversionedasmodifiedticker
= cachetypeticker
;
78 showunversionedoverlayticker
= cachetypeticker
;
79 showignoredoverlayticker
= cachetypeticker
;
80 admindirticker
= cachetypeticker
;
81 columnseverywhereticker
= cachetypeticker
;
82 getlocktopticker
= cachetypeticker
;
83 excludedasnormalticker
= cachetypeticker
;
84 excontextticker
= cachetypeticker
;
85 menulayoutlow
= CRegStdWORD(_T("Software\\TortoiseGit\\ContextMenuEntries"), MENUCREATEREPOS
|MENUCLONE
|MENUUPDATE
|MENUCOMMIT
);
86 menulayouthigh
= CRegStdWORD(_T("Software\\TortoiseGit\\ContextMenuEntrieshigh"), (MENUCREATEREPOS
|MENUCLONE
|MENUUPDATE
|MENUCOMMIT
)>>32);
87 menumasklow_lm
= CRegStdWORD(_T("Software\\TortoiseGit\\ContextMenuEntriesMaskLow"), 0, FALSE
, HKEY_LOCAL_MACHINE
);
88 menumaskhigh_lm
= CRegStdWORD(_T("Software\\TortoiseGit\\ContextMenuEntriesMaskHigh"), 0, FALSE
, HKEY_LOCAL_MACHINE
);
89 menumasklow_cu
= CRegStdWORD(_T("Software\\TortoiseGit\\ContextMenuEntriesMaskLow"), 0);
90 menumaskhigh_cu
= CRegStdWORD(_T("Software\\TortoiseGit\\ContextMenuEntriesMaskHigh"), 0);
91 langid
= CRegStdWORD(_T("Software\\TortoiseGit\\LanguageID"), 1033);
92 blockstatus
= CRegStdWORD(_T("Software\\TortoiseGit\\BlockStatus"), 0);
93 columnseverywhere
= CRegStdWORD(_T("Software\\TortoiseGit\\ColumnsEveryWhere"), FALSE
);
94 for (int i
=0; i
<27; i
++)
96 drivetypecache
[i
] = (UINT
)-1;
98 // A: and B: are floppy disks
99 drivetypecache
[0] = DRIVE_REMOVABLE
;
100 drivetypecache
[1] = DRIVE_REMOVABLE
;
102 columnrevformatticker
= GetTickCount();
103 SecureZeroMemory(&columnrevformat
, sizeof(NUMBERFMT
));
104 GetLocaleInfo(LOCALE_USER_DEFAULT
, LOCALE_SDECIMAL
, &szDecSep
[0], sizeof(szDecSep
));
105 GetLocaleInfo(LOCALE_USER_DEFAULT
, LOCALE_STHOUSAND
, &szThousandsSep
[0], sizeof(szThousandsSep
));
106 columnrevformat
.lpDecimalSep
= szDecSep
;
107 columnrevformat
.lpThousandSep
= szThousandsSep
;
108 GetLocaleInfo(LOCALE_USER_DEFAULT
, LOCALE_SGROUPING
, &szBuffer
[0], sizeof(szBuffer
));
109 columnrevformat
.Grouping
= _ttoi(szBuffer
);
110 GetLocaleInfo(LOCALE_USER_DEFAULT
, LOCALE_INEGNUMBER
, &szBuffer
[0], sizeof(szBuffer
));
111 columnrevformat
.NegativeOrder
= _ttoi(szBuffer
);
112 sAdminDirCacheKey
.reserve(MAX_PATH
); // MAX_PATH as buffer reservation ok.
113 nocontextpaths
= CRegStdString(_T("Software\\TortoiseGit\\NoContextPaths"), _T(""));
119 showrecursive
.read();
120 folderoverlay
.read();
130 simplecontext
.read();
131 unversionedasmodified
.read();
132 showunversionedoverlay
.read();
133 showignoredoverlay
.read();
134 excludedasnormal
.read();
135 menulayoutlow
.read();
136 menulayouthigh
.read();
139 columnseverywhere
.read();
141 menumasklow_lm
.read();
142 menumaskhigh_lm
.read();
143 menumasklow_cu
.read();
144 menumaskhigh_cu
.read();
145 nocontextpaths
.read();
147 CacheType
GetCacheType()
149 if ((GetTickCount() - REGISTRYTIMEOUT
) > cachetypeticker
)
151 cachetypeticker
= GetTickCount();
154 return CacheType(DWORD((cachetype
)));
158 if ((GetTickCount() - REGISTRYTIMEOUT
) > blockstatusticker
)
160 blockstatusticker
= GetTickCount();
163 return (blockstatus
);
165 unsigned __int64
GetMenuLayout()
167 if ((GetTickCount() - REGISTRYTIMEOUT
) > layoutticker
)
169 layoutticker
= GetTickCount();
170 menulayoutlow
.read();
171 menulayouthigh
.read();
173 unsigned __int64 temp
= unsigned __int64(DWORD(menulayouthigh
))<<32;
174 temp
|= unsigned __int64(DWORD(menulayoutlow
));
177 unsigned __int64
GetMenuMask()
179 if ((GetTickCount() - REGISTRYTIMEOUT
) > menumaskticker
)
181 menumaskticker
= GetTickCount();
182 menumasklow_lm
.read();
183 menumaskhigh_lm
.read();
184 menumasklow_cu
.read();
185 menumaskhigh_cu
.read();
187 DWORD low
= (DWORD
)menumasklow_lm
| (DWORD
)menumasklow_cu
;
188 DWORD high
= (DWORD
)menumaskhigh_lm
| (DWORD
)menumaskhigh_cu
;
189 unsigned __int64 temp
= unsigned __int64(high
)<<32;
190 temp
|= unsigned __int64(low
);
195 if ((GetTickCount() - REGISTRYTIMEOUT
)>recursiveticker
)
197 recursiveticker
= GetTickCount();
198 showrecursive
.read();
200 return (showrecursive
);
202 BOOL
IsFolderOverlay()
204 if ((GetTickCount() - REGISTRYTIMEOUT
)>folderoverlayticker
)
206 folderoverlayticker
= GetTickCount();
207 folderoverlay
.read();
209 return (folderoverlay
);
211 BOOL
IsSimpleContext()
213 if ((GetTickCount() - REGISTRYTIMEOUT
)>simplecontextticker
)
215 simplecontextticker
= GetTickCount();
216 simplecontext
.read();
218 return (simplecontext
!=0);
220 BOOL
IsUnversionedAsModified()
222 if ((GetTickCount() - REGISTRYTIMEOUT
)>unversionedasmodifiedticker
)
224 unversionedasmodifiedticker
= GetTickCount();
225 unversionedasmodified
.read();
227 return (unversionedasmodified
);
229 BOOL
ShowUnversionedOverlay()
231 if ((GetTickCount() - REGISTRYTIMEOUT
)>showunversionedoverlayticker
)
233 showunversionedoverlayticker
= GetTickCount();
234 showunversionedoverlay
.read();
236 return (showunversionedoverlay
);
238 BOOL
ShowIgnoredOverlay()
240 if ((GetTickCount() - REGISTRYTIMEOUT
)>showignoredoverlayticker
)
242 showignoredoverlayticker
= GetTickCount();
243 showignoredoverlay
.read();
245 return (showignoredoverlay
);
249 if ((GetTickCount() - REGISTRYTIMEOUT
)>getlocktopticker
)
251 getlocktopticker
= GetTickCount();
256 BOOL
ShowExcludedAsNormal()
258 if ((GetTickCount() - REGISTRYTIMEOUT
)>excludedasnormalticker
)
260 excludedasnormalticker
= GetTickCount();
261 excludedasnormal
.read();
263 return (excludedasnormal
);
268 return (driveremote
);
283 return (driveremove
);
293 return (driveunknown
);
295 BOOL
IsContextPathAllowed(LPCTSTR path
)
297 Locker
lock(m_critSec
);
298 ExcludeContextValid();
299 for (std::vector
<stdstring
>::iterator I
= excontextvector
.begin(); I
!= excontextvector
.end(); ++I
)
303 if (I
->size() && I
->at(I
->size()-1)=='*')
305 stdstring str
= I
->substr(0, I
->size()-1);
306 if (_tcsnicmp(str
.c_str(), path
, str
.size())==0)
309 else if (_tcsicmp(I
->c_str(), path
)==0)
314 BOOL
IsPathAllowed(LPCTSTR path
)
316 Locker
lock(m_critSec
);
318 for (std::vector
<stdstring
>::iterator I
= invector
.begin(); I
!= invector
.end(); ++I
)
322 if (I
->at(I
->size()-1)=='*')
324 stdstring str
= I
->substr(0, I
->size()-1);
325 if (_tcsnicmp(str
.c_str(), path
, str
.size())==0)
327 if (str
.size() && (str
.at(str
.size()-1) == '\\') && (_tcsnicmp(str
.c_str(), path
, str
.size()-1)==0))
330 else if (_tcsicmp(I
->c_str(), path
)==0)
332 else if ((I
->at(I
->size()-1) == '\\') &&
333 ((_tcsnicmp(I
->c_str(), path
, I
->size())==0) || (_tcsicmp(I
->c_str(), path
)==0)) )
338 int drivenumber
= PathGetDriveNumber(path
);
339 if ((drivenumber
>=0)&&(drivenumber
< 25))
341 drivetype
= drivetypecache
[drivenumber
];
342 if ((drivetype
== -1)||((GetTickCount() - DRIVETYPETIMEOUT
)>drivetypeticker
))
344 if ((drivenumber
== 0)||(drivenumber
== 1))
345 drivetypecache
[drivenumber
] = DRIVE_REMOVABLE
;
348 drivetypeticker
= GetTickCount();
349 TCHAR pathbuf
[MAX_PATH
+4]; // MAX_PATH ok here. PathStripToRoot works with partial paths too.
350 _tcsncpy_s(pathbuf
, MAX_PATH
+4, path
, MAX_PATH
+3);
351 PathStripToRoot(pathbuf
);
352 PathAddBackslash(pathbuf
);
353 ATLTRACE2(_T("GetDriveType for %s, Drive %d\n"), pathbuf
, drivenumber
);
354 drivetype
= GetDriveType(pathbuf
);
355 drivetypecache
[drivenumber
] = drivetype
;
361 TCHAR pathbuf
[MAX_PATH
+4]; // MAX_PATH ok here. PathIsUNCServer works with partial paths too.
362 _tcsncpy_s(pathbuf
, MAX_PATH
+4, path
, MAX_PATH
+3);
363 if (PathIsUNCServer(pathbuf
))
364 drivetype
= DRIVE_REMOTE
;
367 PathStripToRoot(pathbuf
);
368 PathAddBackslash(pathbuf
);
369 if (_tcsncmp(pathbuf
, drivetypepathcache
, MAX_PATH
-1)==0) // MAX_PATH ok.
370 drivetype
= drivetypecache
[26];
373 ATLTRACE2(_T("GetDriveType for %s\n"), pathbuf
);
374 drivetype
= GetDriveType(pathbuf
);
375 drivetypecache
[26] = drivetype
;
376 _tcsncpy_s(drivetypepathcache
, MAX_PATH
, pathbuf
, MAX_PATH
); // MAX_PATH ok.
380 if ((drivetype
== DRIVE_REMOVABLE
)&&(!IsRemovable()))
382 if ((drivetype
== DRIVE_REMOVABLE
)&&(drivefloppy
== 0)&&((drivenumber
==0)||(drivenumber
==1)))
384 if ((drivetype
== DRIVE_FIXED
)&&(!IsFixed()))
386 if (((drivetype
== DRIVE_REMOTE
)||(drivetype
== DRIVE_NO_ROOT_DIR
))&&(!IsRemote()))
388 if ((drivetype
== DRIVE_CDROM
)&&(!IsCDRom()))
390 if ((drivetype
== DRIVE_RAMDISK
)&&(!IsRAM()))
392 if ((drivetype
== DRIVE_UNKNOWN
)&&(IsUnknown()))
396 for (std::vector
<stdstring
>::iterator I
= exvector
.begin(); I
!= exvector
.end(); ++I
)
400 if (I
->size() && I
->at(I
->size()-1)=='*')
402 stdstring str
= I
->substr(0, I
->size()-1);
403 if (_tcsnicmp(str
.c_str(), path
, str
.size())==0)
406 else if (_tcsicmp(I
->c_str(), path
)==0)
413 if ((GetTickCount() - REGISTRYTIMEOUT
) > langticker
)
415 langticker
= GetTickCount();
420 NUMBERFMT
* GetNumberFmt()
422 if ((GetTickCount() - NUMBERFMTTIMEOUT
) > columnrevformatticker
)
425 columnrevformatticker
= GetTickCount();
426 SecureZeroMemory(&columnrevformat
, sizeof(NUMBERFMT
));
427 GetLocaleInfo(LOCALE_USER_DEFAULT
, LOCALE_SDECIMAL
, &szDecSep
[0], sizeof(szDecSep
));
428 GetLocaleInfo(LOCALE_USER_DEFAULT
, LOCALE_STHOUSAND
, &szThousandsSep
[0], sizeof(szThousandsSep
));
429 columnrevformat
.lpDecimalSep
= szDecSep
;
430 columnrevformat
.lpThousandSep
= szThousandsSep
;
431 GetLocaleInfo(LOCALE_USER_DEFAULT
, LOCALE_SGROUPING
, &szBuffer
[0], sizeof(szBuffer
));
432 columnrevformat
.Grouping
= _ttoi(szBuffer
);
433 GetLocaleInfo(LOCALE_USER_DEFAULT
, LOCALE_INEGNUMBER
, &szBuffer
[0], sizeof(szBuffer
));
434 columnrevformat
.NegativeOrder
= _ttoi(szBuffer
);
436 return &columnrevformat
;
438 BOOL
HasSVNAdminDir(LPCTSTR path
, BOOL bIsDir
, CString
*ProjectTopDir
= NULL
)
440 size_t len
= _tcslen(path
);
441 TCHAR
* buf
= new TCHAR
[len
+1];
442 _tcscpy_s(buf
, len
+1, path
);
445 TCHAR
* ptr
= _tcsrchr(buf
, '\\');
451 if ((GetTickCount() - ADMINDIRTIMEOUT
) < admindirticker
)
453 std::map
<stdstring
, AdminDir_s
>::iterator iter
;
454 sAdminDirCacheKey
.assign(buf
);
455 if ((iter
= admindircache
.find(sAdminDirCacheKey
)) != admindircache
.end())
458 if (ProjectTopDir
&& iter
->second
.bHasAdminDir
)
459 *ProjectTopDir
= iter
->second
.sProjectRoot
.c_str();
460 return iter
->second
.bHasAdminDir
;
463 CString sProjectRoot
;
464 BOOL hasAdminDir
= g_GitAdminDir
.HasAdminDir(buf
, true, &sProjectRoot
);
465 admindirticker
= GetTickCount();
466 Locker
lock(m_critSec
);
468 AdminDir_s
&ad
= admindircache
[buf
];
469 ad
.bHasAdminDir
= hasAdminDir
;
472 ad
.sProjectRoot
.assign(sProjectRoot
);
475 *ProjectTopDir
= sProjectRoot
;
481 bool IsColumnsEveryWhere()
483 if ((GetTickCount() - REGISTRYTIMEOUT
) > columnseverywhereticker
)
485 columnseverywhereticker
= GetTickCount();
486 columnseverywhere
.read();
488 return !!(DWORD
)columnseverywhere
;
493 if ((GetTickCount() - REGISTRYTIMEOUT
)>driveticker
)
495 driveticker
= GetTickCount();
503 void ExcludeContextValid()
505 if ((GetTickCount() - EXCLUDELISTTIMEOUT
)>excontextticker
)
507 Locker
lock(m_critSec
);
508 excontextticker
= GetTickCount();
509 nocontextpaths
.read();
510 if (excludecontextstr
.compare((stdstring
)nocontextpaths
)==0)
512 excludecontextstr
= (stdstring
)nocontextpaths
;
513 excontextvector
.clear();
514 size_t pos
= 0, pos_ant
= 0;
515 pos
= excludecontextstr
.find(_T("\n"), pos_ant
);
516 while (pos
!= stdstring::npos
)
518 stdstring token
= excludecontextstr
.substr(pos_ant
, pos
-pos_ant
);
519 excontextvector
.push_back(token
);
521 pos
= excludecontextstr
.find(_T("\n"), pos_ant
);
523 if (!excludecontextstr
.empty())
525 excontextvector
.push_back(excludecontextstr
.substr(pos_ant
, excludecontextstr
.size()-1));
527 excludecontextstr
= (stdstring
)nocontextpaths
;
530 void ExcludeListValid()
532 if ((GetTickCount() - EXCLUDELISTTIMEOUT
)>excludelistticker
)
534 Locker
lock(m_critSec
);
535 excludelistticker
= GetTickCount();
537 if (excludeliststr
.compare((stdstring
)excludelist
)==0)
539 excludeliststr
= (stdstring
)excludelist
;
541 size_t pos
= 0, pos_ant
= 0;
542 pos
= excludeliststr
.find(_T("\n"), pos_ant
);
543 while (pos
!= stdstring::npos
)
545 stdstring token
= excludeliststr
.substr(pos_ant
, pos
-pos_ant
);
546 exvector
.push_back(token
);
548 pos
= excludeliststr
.find(_T("\n"), pos_ant
);
550 if (!excludeliststr
.empty())
552 exvector
.push_back(excludeliststr
.substr(pos_ant
, excludeliststr
.size()-1));
554 excludeliststr
= (stdstring
)excludelist
;
557 void IncludeListValid()
559 if ((GetTickCount() - EXCLUDELISTTIMEOUT
)>includelistticker
)
561 Locker
lock(m_critSec
);
562 includelistticker
= GetTickCount();
564 if (includeliststr
.compare((stdstring
)includelist
)==0)
566 includeliststr
= (stdstring
)includelist
;
568 size_t pos
= 0, pos_ant
= 0;
569 pos
= includeliststr
.find(_T("\n"), pos_ant
);
570 while (pos
!= stdstring::npos
)
572 stdstring token
= includeliststr
.substr(pos_ant
, pos
-pos_ant
);
573 invector
.push_back(token
);
575 pos
= includeliststr
.find(_T("\n"), pos_ant
);
577 if (!includeliststr
.empty())
579 invector
.push_back(includeliststr
.substr(pos_ant
, includeliststr
.size()-1));
581 includeliststr
= (stdstring
)includelist
;
588 stdstring sProjectRoot
;
591 CRegStdWORD cachetype
;
592 CRegStdWORD blockstatus
;
594 CRegStdWORD showrecursive
;
595 CRegStdWORD folderoverlay
;
596 CRegStdWORD getlocktop
;
597 CRegStdWORD driveremote
;
598 CRegStdWORD drivefixed
;
599 CRegStdWORD drivecdrom
;
600 CRegStdWORD driveremove
;
601 CRegStdWORD drivefloppy
;
602 CRegStdWORD driveram
;
603 CRegStdWORD driveunknown
;
604 CRegStdWORD menulayoutlow
;
605 CRegStdWORD menulayouthigh
;
606 CRegStdWORD simplecontext
;
607 CRegStdWORD menumasklow_lm
;
608 CRegStdWORD menumaskhigh_lm
;
609 CRegStdWORD menumasklow_cu
;
610 CRegStdWORD menumaskhigh_cu
;
611 CRegStdWORD unversionedasmodified
;
612 CRegStdWORD showunversionedoverlay
;
613 CRegStdWORD showignoredoverlay
;
614 CRegStdWORD excludedasnormal
;
615 CRegStdString excludelist
;
616 CRegStdWORD columnseverywhere
;
617 stdstring excludeliststr
;
618 std::vector
<stdstring
> exvector
;
619 CRegStdString includelist
;
620 stdstring includeliststr
;
621 std::vector
<stdstring
> invector
;
622 DWORD cachetypeticker
;
623 DWORD recursiveticker
;
624 DWORD folderoverlayticker
;
625 DWORD getlocktopticker
;
627 DWORD drivetypeticker
;
629 DWORD menumaskticker
;
631 DWORD blockstatusticker
;
632 DWORD columnrevformatticker
;
633 DWORD excludelistticker
;
634 DWORD includelistticker
;
635 DWORD simplecontextticker
;
636 DWORD unversionedasmodifiedticker
;
637 DWORD showunversionedoverlayticker
;
638 DWORD showignoredoverlayticker
;
639 DWORD excludedasnormalticker
;
640 DWORD columnseverywhereticker
;
641 UINT drivetypecache
[27];
642 TCHAR drivetypepathcache
[MAX_PATH
]; // MAX_PATH ok.
643 NUMBERFMT columnrevformat
;
645 TCHAR szThousandsSep
[5];
646 std::map
<stdstring
, AdminDir_s
> admindircache
;
647 stdstring sAdminDirCacheKey
;
648 CRegStdString nocontextpaths
;
649 stdstring excludecontextstr
;
650 std::vector
<stdstring
> excontextvector
;
651 DWORD excontextticker
;
652 DWORD admindirticker
;
653 CComCriticalSection m_critSec
;