OSDN Git Service

Init Version
authorFrank Li <Frank.li@freescale.com>
Wed, 5 Nov 2008 13:57:36 +0000 (21:57 +0800)
committerFrank Li <Frank.li@freescale.com>
Wed, 5 Nov 2008 13:57:36 +0000 (21:57 +0800)
36 files changed:
TortoiseShell/ColumnProvider.cpp [new file with mode: 0644]
TortoiseShell/ContextMenu.cpp [new file with mode: 0644]
TortoiseShell/Documentation.h [new file with mode: 0644]
TortoiseShell/Globals.h [new file with mode: 0644]
TortoiseShell/Guids.h [new file with mode: 0644]
TortoiseShell/IconOverlay.cpp [new file with mode: 0644]
TortoiseShell/ItemIDList.cpp [new file with mode: 0644]
TortoiseShell/ItemIDList.h [new file with mode: 0644]
TortoiseShell/PIDL.cpp [new file with mode: 0644]
TortoiseShell/PIDL.h [new file with mode: 0644]
TortoiseShell/PreserveChdir.cpp [new file with mode: 0644]
TortoiseShell/PreserveChdir.h [new file with mode: 0644]
TortoiseShell/RemoteCacheLink.cpp [new file with mode: 0644]
TortoiseShell/RemoteCacheLink.h [new file with mode: 0644]
TortoiseShell/SVNPropertyPage.cpp [new file with mode: 0644]
TortoiseShell/SVNPropertyPage.h [new file with mode: 0644]
TortoiseShell/ShellCache.h [new file with mode: 0644]
TortoiseShell/ShellExt.cpp [new file with mode: 0644]
TortoiseShell/ShellExt.def [new file with mode: 0644]
TortoiseShell/ShellExt.h [new file with mode: 0644]
TortoiseShell/ShellExtClassFactory.cpp [new file with mode: 0644]
TortoiseShell/ShellExtClassFactory.h [new file with mode: 0644]
TortoiseShell/TortoiseSVN.cpp [new file with mode: 0644]
TortoiseShell/TortoiseShell.vcproj [new file with mode: 0644]
TortoiseShell/TortoiseStub.c [new file with mode: 0644]
TortoiseShell/TortoiseStub.def [new file with mode: 0644]
TortoiseShell/TortoiseStub.rc [new file with mode: 0644]
TortoiseShell/TortoiseStub.vcproj [new file with mode: 0644]
TortoiseShell/deregister.registry [new file with mode: 0644]
TortoiseShell/register.registry [new file with mode: 0644]
TortoiseShell/registerrelease.registry [new file with mode: 0644]
TortoiseShell/resource.h [new file with mode: 0644]
TortoiseShell/resource.rc [new file with mode: 0644]
TortoiseShell/resource.rc2 [new file with mode: 0644]
TortoiseShell/stdafx.cpp [new file with mode: 0644]
TortoiseShell/stdafx.h [new file with mode: 0644]

diff --git a/TortoiseShell/ColumnProvider.cpp b/TortoiseShell/ColumnProvider.cpp
new file mode 100644 (file)
index 0000000..b48671a
--- /dev/null
@@ -0,0 +1,461 @@
+// TortoiseSVN - a Windows shell extension for easy version control\r
+\r
+// Copyright (C) 2003-2008 - TortoiseSVN\r
+\r
+// This program is free software; you can redistribute it and/or\r
+// modify it under the terms of the GNU General Public License\r
+// as published by the Free Software Foundation; either version 2\r
+// of the License, or (at your option) any later version.\r
+\r
+// This program is distributed in the hope that it will be useful,\r
+// but WITHOUT ANY WARRANTY; without even the implied warranty of\r
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\r
+// GNU General Public License for more details.\r
+\r
+// You should have received a copy of the GNU General Public License\r
+// along with this program; if not, write to the Free Software Foundation,\r
+// 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.\r
+//\r
+#include "stdafx.h"\r
+#include "ShellExt.h"\r
+#include "guids.h"\r
+#include "PreserveChdir.h"\r
+#include "SVNProperties.h"\r
+#include "UnicodeUtils.h"\r
+#include "SVNStatus.h"\r
+#include "PathUtils.h"\r
+#include "..\TSVNCache\CacheInterface.h"\r
+\r
+\r
+const static int ColumnFlags = SHCOLSTATE_TYPE_STR | SHCOLSTATE_ONBYDEFAULT;\r
+\r
+// Defines that revision numbers occupy at most MAX_REV_STRING_LEN characters.\r
+// There are Perforce repositories out there that have several 100,000 revs.\r
+// So, don't be too restrictive by limiting this to 6 digits + 1 separator, \r
+// for instance. \r
+//\r
+// Because shorter strings will be extended to have exactly MAX_REV_STRING_LEN \r
+// characters, large numbers will produce large strings. These, in turn, will\r
+// affect column auto sizing. This setting is a reasonable compromise.\r
+//\r
+// Max rev correctly sorted: 99,999,999 for MAX_REV_STRING_LEN == 10\r
+\r
+#define MAX_REV_STRING_LEN 10\r
+\r
+// IColumnProvider members\r
+STDMETHODIMP CShellExt::GetColumnInfo(DWORD dwIndex, SHCOLUMNINFO *psci)\r
+{\r
+       PreserveChdir preserveChdir;\r
+       if (dwIndex > 8)\r
+               return S_FALSE;\r
+\r
+       ShellCache::CacheType cachetype = g_ShellCache.GetCacheType();\r
+       LoadLangDll();\r
+       wide_string ws;\r
+       switch (dwIndex)\r
+       {\r
+               case 0: // SVN Status\r
+                       if (cachetype == ShellCache::none)\r
+                               return S_FALSE;\r
+                       psci->scid.fmtid = CLSID_TortoiseSVN_UPTODATE;\r
+                       psci->scid.pid = dwIndex;\r
+                       psci->vt = VT_BSTR;\r
+                       psci->fmt = LVCFMT_LEFT;\r
+                       psci->cChars = 15;\r
+                       psci->csFlags = ColumnFlags;\r
+\r
+                       MAKESTRING(IDS_COLTITLESTATUS);\r
+                       lstrcpynW(psci->wszTitle, stringtablebuffer, MAX_COLUMN_NAME_LEN);\r
+                       MAKESTRING(IDS_COLDESCSTATUS);\r
+                       lstrcpynW(psci->wszDescription, stringtablebuffer, MAX_COLUMN_DESC_LEN);\r
+                       break;\r
+               case 1: // SVN Revision\r
+                       if (cachetype == ShellCache::none)\r
+                               return S_FALSE;\r
+                       psci->scid.fmtid = CLSID_TortoiseSVN_UPTODATE;\r
+                       psci->scid.pid = dwIndex;\r
+                       psci->vt = VT_I4;\r
+                       psci->fmt = LVCFMT_RIGHT;\r
+                       psci->cChars = 15;\r
+                       psci->csFlags = SHCOLSTATE_TYPE_INT | SHCOLSTATE_ONBYDEFAULT;\r
+\r
+                       MAKESTRING(IDS_COLTITLEREV);\r
+                       lstrcpynW(psci->wszTitle, stringtablebuffer, MAX_COLUMN_NAME_LEN);\r
+                       MAKESTRING(IDS_COLDESCREV);\r
+                       lstrcpynW(psci->wszDescription, stringtablebuffer, MAX_COLUMN_DESC_LEN);\r
+                       break;\r
+               case 2: // SVN Url\r
+                       if (cachetype == ShellCache::none)\r
+                               return S_FALSE;\r
+                       psci->scid.fmtid = CLSID_TortoiseSVN_UPTODATE;\r
+                       psci->scid.pid = dwIndex;\r
+                       psci->vt = VT_BSTR;\r
+                       psci->fmt = LVCFMT_LEFT;\r
+                       psci->cChars = 30;\r
+                       psci->csFlags = ColumnFlags;\r
+\r
+                       MAKESTRING(IDS_COLTITLEURL);\r
+                       lstrcpynW(psci->wszTitle, stringtablebuffer, MAX_COLUMN_NAME_LEN);\r
+                       MAKESTRING(IDS_COLDESCURL);\r
+                       lstrcpynW(psci->wszDescription, stringtablebuffer, MAX_COLUMN_DESC_LEN);\r
+                       break;\r
+               case 3: // SVN Short Url\r
+                       if (cachetype == ShellCache::none)\r
+                               return S_FALSE;\r
+                       psci->scid.fmtid = CLSID_TortoiseSVN_UPTODATE;\r
+                       psci->scid.pid = dwIndex;\r
+                       psci->vt = VT_BSTR;\r
+                       psci->fmt = LVCFMT_LEFT;\r
+                       psci->cChars = 30;\r
+                       psci->csFlags = ColumnFlags;\r
+\r
+                       MAKESTRING(IDS_COLTITLESHORTURL);\r
+                       lstrcpynW(psci->wszTitle, stringtablebuffer, MAX_COLUMN_NAME_LEN);\r
+                       MAKESTRING(IDS_COLDESCSHORTURL);\r
+                       lstrcpynW(psci->wszDescription, stringtablebuffer, MAX_COLUMN_DESC_LEN);\r
+                       break;\r
+               case 4: // Author\r
+                       if (cachetype == ShellCache::none)\r
+                               return S_FALSE;\r
+                       psci->scid.fmtid = FMTID_SummaryInformation;    // predefined FMTID\r
+                       psci->scid.pid   = PIDSI_AUTHOR;                                // Predefined - author\r
+                       psci->vt         = VT_LPSTR;                                    // We'll return the data as a string\r
+                       psci->fmt        = LVCFMT_LEFT;                                 // Text will be left-aligned in the column\r
+                       psci->csFlags    = SHCOLSTATE_TYPE_STR;                 // Data should be sorted as strings\r
+                       psci->cChars     = 32;                                                  // Default col width in chars\r
+                       break;\r
+               case 5: // SVN mime-type\r
+                       if (cachetype == ShellCache::none)\r
+                               return S_FALSE;\r
+                       psci->scid.fmtid = CLSID_TortoiseSVN_UPTODATE;\r
+                       psci->scid.pid = dwIndex;\r
+                       psci->vt = VT_BSTR;\r
+                       psci->fmt = LVCFMT_LEFT;\r
+                       psci->cChars = 30;\r
+                       psci->csFlags = ColumnFlags;\r
+\r
+                       MAKESTRING(IDS_COLTITLEMIMETYPE);\r
+                       lstrcpynW(psci->wszTitle, stringtablebuffer, MAX_COLUMN_NAME_LEN);\r
+                       MAKESTRING(IDS_COLDESCMIMETYPE);\r
+                       lstrcpynW(psci->wszDescription, stringtablebuffer, MAX_COLUMN_DESC_LEN);\r
+                       break;\r
+               case 6: // SVN Lock Owner\r
+                       if (cachetype == ShellCache::none)\r
+                               return S_FALSE;\r
+                       psci->scid.fmtid = CLSID_TortoiseSVN_UPTODATE;\r
+                       psci->scid.pid = dwIndex;\r
+                       psci->vt = VT_BSTR;\r
+                       psci->fmt = LVCFMT_LEFT;\r
+                       psci->cChars = 30;\r
+                       psci->csFlags = ColumnFlags;\r
+\r
+                       MAKESTRING(IDS_COLTITLEOWNER);\r
+                       lstrcpynW(psci->wszTitle, stringtablebuffer, MAX_COLUMN_NAME_LEN);\r
+                       MAKESTRING(IDS_COLDESCOWNER);\r
+                       lstrcpynW(psci->wszDescription, stringtablebuffer, MAX_COLUMN_DESC_LEN);\r
+                       break;\r
+               case 7: // SVN eol-style\r
+                       if (cachetype == ShellCache::none)\r
+                               return S_FALSE;\r
+                       psci->scid.fmtid = CLSID_TortoiseSVN_UPTODATE;\r
+                       psci->scid.pid = dwIndex;\r
+                       psci->vt = VT_BSTR;\r
+                       psci->fmt = LVCFMT_LEFT;\r
+                       psci->cChars = 30;\r
+                       psci->csFlags = ColumnFlags;\r
+\r
+                       MAKESTRING(IDS_COLTITLEEOLSTYLE);\r
+                       lstrcpynW(psci->wszTitle, stringtablebuffer, MAX_COLUMN_NAME_LEN);\r
+                       MAKESTRING(IDS_COLDESCEOLSTYLE);\r
+                       lstrcpynW(psci->wszDescription, stringtablebuffer, MAX_COLUMN_DESC_LEN);\r
+                       break;\r
+               case 8: // SVN Author\r
+                       if (cachetype == ShellCache::none)\r
+                               return S_FALSE;\r
+                       psci->scid.fmtid = CLSID_TortoiseSVN_UPTODATE;\r
+                       psci->scid.pid = dwIndex;\r
+                       psci->vt = VT_BSTR;\r
+                       psci->fmt = LVCFMT_LEFT;\r
+                       psci->cChars = 30;\r
+                       psci->csFlags = ColumnFlags;\r
+\r
+                       MAKESTRING(IDS_COLTITLEAUTHOR);\r
+                       lstrcpynW(psci->wszTitle, stringtablebuffer, MAX_COLUMN_NAME_LEN);\r
+                       MAKESTRING(IDS_COLDESCAUTHOR);\r
+                       lstrcpynW(psci->wszDescription, stringtablebuffer, MAX_COLUMN_DESC_LEN);\r
+                       break;\r
+       }\r
+\r
+       return S_OK;\r
+}\r
+\r
+STDMETHODIMP CShellExt::GetItemData(LPCSHCOLUMNID pscid, LPCSHCOLUMNDATA pscd, VARIANT *pvarData)\r
+{\r
+       PreserveChdir preserveChdir;\r
+       if (!g_ShellCache.IsPathAllowed((TCHAR *)pscd->wszFile))\r
+       {\r
+               return S_FALSE;\r
+       }\r
+       LoadLangDll();\r
+       ShellCache::CacheType cachetype = g_ShellCache.GetCacheType();\r
+       if (pscid->fmtid == CLSID_TortoiseSVN_UPTODATE && pscid->pid < 8) \r
+       {\r
+               stdstring szInfo;\r
+               const TCHAR * path = (TCHAR *)pscd->wszFile;\r
+\r
+               // reserve for the path + trailing \0\r
+\r
+               TCHAR buf[MAX_STATUS_STRING_LENGTH+1];\r
+               SecureZeroMemory(buf, MAX_STATUS_STRING_LENGTH);\r
+               switch (pscid->pid) \r
+               {\r
+                       case 0: // SVN Status\r
+                               GetColumnStatus(path, pscd->dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY);\r
+                               SVNStatus::GetStatusString(g_hResInst, filestatus, buf, sizeof(buf)/sizeof(TCHAR), (WORD)CRegStdWORD(_T("Software\\TortoiseSVN\\LanguageID"), MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT)));\r
+                               szInfo = buf;\r
+                               break;\r
+                       case 1: // SVN Revision\r
+                               GetColumnStatus(path, pscd->dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY);\r
+                               if (columnrev >= 0)\r
+                               {\r
+                                       V_VT(pvarData) = VT_I4;\r
+                                       V_I4(pvarData) = columnrev;\r
+                               }\r
+                               return S_OK;\r
+                               break;\r
+                       case 2: // SVN Url\r
+                               GetColumnStatus(path, pscd->dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY);\r
+                               szInfo = itemurl;\r
+                               break;\r
+                       case 3: // SVN Short Url\r
+                               GetColumnStatus(path, pscd->dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY);\r
+                               szInfo = itemshorturl;\r
+                               break;\r
+                       case 5: // SVN mime-type\r
+                               if (cachetype == ShellCache::none)\r
+                                       return S_FALSE;\r
+                               if (g_ShellCache.IsPathAllowed(path))\r
+                               {\r
+                                       SVNProperties props = SVNProperties(CTSVNPath(path), false);\r
+                                       for (int i=0; i<props.GetCount(); i++)\r
+                                       {\r
+                                               if (props.GetItemName(i).compare(_T("svn:mime-type"))==0)\r
+                                               {\r
+                                                       szInfo = MultibyteToWide((char *)props.GetItemValue(i).c_str());\r
+                                               }\r
+                                       }\r
+                               }\r
+                               break;\r
+                       case 6: // SVN Lock Owner\r
+                               GetColumnStatus(path, pscd->dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY);\r
+                               szInfo = owner;\r
+                               break;\r
+                       case 7: // SVN eol-style\r
+                               if (cachetype == ShellCache::none)\r
+                                       return S_FALSE;\r
+                               if (g_ShellCache.IsPathAllowed(path))\r
+                               {\r
+                                       SVNProperties props = SVNProperties(CTSVNPath(path), false);\r
+                                       for (int i=0; i<props.GetCount(); i++)\r
+                                       {\r
+                                               if (props.GetItemName(i).compare(_T("svn:eol-style"))==0)\r
+                                               {\r
+                                                       szInfo = MultibyteToWide((char *)props.GetItemValue(i).c_str());\r
+                                               }\r
+                                       }\r
+                               }\r
+                               break;\r
+                       default:\r
+                               return S_FALSE;\r
+               }\r
+               const WCHAR * wsInfo = szInfo.c_str();\r
+               V_VT(pvarData) = VT_BSTR;\r
+               V_BSTR(pvarData) = SysAllocString(wsInfo);\r
+               return S_OK;\r
+       }\r
+       if ((pscid->fmtid == FMTID_SummaryInformation)||(pscid->pid == 8))\r
+       {\r
+               stdstring szInfo;\r
+               const TCHAR * path = pscd->wszFile;\r
+\r
+               if (cachetype == ShellCache::none)\r
+                       return S_FALSE;\r
+               switch (pscid->pid)\r
+               {\r
+               case PIDSI_AUTHOR:                      // author\r
+               case 8:\r
+                       GetColumnStatus(path, pscd->dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY);\r
+                       szInfo = columnauthor;\r
+                       break;\r
+               default:\r
+                       return S_FALSE;\r
+               }\r
+               wide_string wsInfo = szInfo;\r
+               V_VT(pvarData) = VT_BSTR;\r
+               V_BSTR(pvarData) = SysAllocString(wsInfo.c_str());\r
+               return S_OK;\r
+       }\r
+\r
+       return S_FALSE;\r
+}\r
+\r
+STDMETHODIMP CShellExt::Initialize(LPCSHCOLUMNINIT psci)\r
+{\r
+       // psci->wszFolder (WCHAR) holds the path to the folder to be displayed\r
+       // Should check to see if its a "SVN" folder and if not return E_FAIL\r
+\r
+       PreserveChdir preserveChdir;\r
+       if (g_ShellCache.IsColumnsEveryWhere())\r
+               return S_OK;\r
+       std::wstring path = psci->wszFolder;\r
+       if (!path.empty())\r
+       {\r
+               if (! g_ShellCache.HasSVNAdminDir(path.c_str(), TRUE))\r
+                       return E_FAIL;\r
+       }\r
+       columnfilepath = _T("");\r
+       return S_OK;\r
+}\r
+\r
+void CShellExt::GetColumnStatus(const TCHAR * path, BOOL bIsDir)\r
+{\r
+       PreserveChdir preserveChdir;\r
+       if (_tcscmp(path, columnfilepath.c_str())==0)\r
+               return;\r
+       LoadLangDll();\r
+       columnfilepath = path;\r
+       const FileStatusCacheEntry * status = NULL;\r
+       TSVNCacheResponse itemStatus;\r
+       ShellCache::CacheType t = ShellCache::exe;\r
+       AutoLocker lock(g_csGlobalCOMGuard);\r
+       t = g_ShellCache.GetCacheType();\r
+\r
+       switch (t)\r
+       {\r
+       case ShellCache::exe:\r
+               {\r
+                       SecureZeroMemory(&itemStatus, sizeof(itemStatus));\r
+                       if(m_remoteCacheLink.GetStatusFromRemoteCache(CTSVNPath(path), &itemStatus, true))\r
+                       {\r
+                               filestatus = SVNStatus::GetMoreImportant(itemStatus.m_status.text_status, itemStatus.m_status.prop_status);\r
+                       }\r
+                       else\r
+                       {\r
+                               filestatus = svn_wc_status_none;\r
+                               columnauthor.clear();\r
+                               columnrev = 0;\r
+                               itemurl.clear();\r
+                               itemshorturl.clear();\r
+                               owner.clear();\r
+                               return; \r
+                       }\r
+               }\r
+               break;\r
+       case ShellCache::dll:\r
+               {\r
+                       status = m_CachedStatus.GetFullStatus(CTSVNPath(path), bIsDir, TRUE);\r
+                       filestatus = status->status;\r
+               }\r
+               break;\r
+       default:\r
+       case ShellCache::none:\r
+               {\r
+                       if (g_ShellCache.HasSVNAdminDir(path, bIsDir))\r
+                               filestatus = svn_wc_status_normal;\r
+                       else\r
+                               filestatus = svn_wc_status_none;\r
+                       columnauthor.clear();\r
+                       columnrev = 0;\r
+                       itemurl.clear();\r
+                       itemshorturl.clear();\r
+                       owner.clear();\r
+                       return; \r
+               }\r
+               break;\r
+       }\r
+\r
+       if (t == ShellCache::exe)\r
+       {\r
+               columnauthor = UTF8ToWide(itemStatus.m_author);\r
+               columnrev = itemStatus.m_entry.cmt_rev;\r
+               itemurl = UTF8ToWide(itemStatus.m_url);\r
+               owner = UTF8ToWide(itemStatus.m_owner);\r
+       }\r
+       else\r
+       {\r
+               if (status)\r
+               {\r
+                       columnauthor = UTF8ToWide(status->author);\r
+                       columnrev = status->rev;\r
+                       itemurl = UTF8ToWide(status->url);\r
+                       owner = UTF8ToWide(status->owner);\r
+               }\r
+       }\r
+       TCHAR urlpath[INTERNET_MAX_URL_LENGTH+1];\r
+\r
+       URL_COMPONENTS urlComponents;\r
+       memset(&urlComponents, 0, sizeof(URL_COMPONENTS));\r
+       urlComponents.dwStructSize = sizeof(URL_COMPONENTS);\r
+       urlComponents.dwUrlPathLength = INTERNET_MAX_URL_LENGTH;\r
+       urlComponents.lpszUrlPath = urlpath;\r
+       if (InternetCrackUrl(itemurl.c_str(), 0, ICU_DECODE, &urlComponents))\r
+       {\r
+               // since the short url is shown as an additional column where the\r
+               // file/foldername is shown too, we strip that name from the url\r
+               // to make the url even shorter.\r
+               TCHAR * ptr = _tcsrchr(urlComponents.lpszUrlPath, '/');\r
+               if (ptr == NULL)\r
+                       ptr = _tcsrchr(urlComponents.lpszUrlPath, '\\');\r
+               if (ptr)\r
+               {\r
+                       *ptr = '\0';\r
+                       // to shorten the url even more, we check for 'trunk', 'branches' and 'tags'\r
+                       // and simply assume that these are the folders attached to the repository\r
+                       // root. If we find those, we strip the whole path before those folders too.\r
+                       // Note: this will strip too much if such a folder is *below* the repository\r
+                       // root - but it's called 'short url' and we're free to shorten it the way we\r
+                       // like :)\r
+                       ptr = _tcsstr(urlComponents.lpszUrlPath, _T("/trunk"));\r
+                       if (ptr == NULL)\r
+                               ptr = _tcsstr(urlComponents.lpszUrlPath, _T("\\trunk"));\r
+                       if ((ptr == NULL)||((*(ptr+6) != 0)&&(*(ptr+6) != '/')&&(*(ptr+6) != '\\')))\r
+                       {\r
+                               ptr = _tcsstr(urlComponents.lpszUrlPath, _T("/branches"));\r
+                               if (ptr == NULL)\r
+                                       ptr = _tcsstr(urlComponents.lpszUrlPath, _T("\\branches"));\r
+                               if ((ptr == NULL)||((*(ptr+9) != 0)&&(*(ptr+9) != '/')&&(*(ptr+9) != '\\')))\r
+                               {\r
+                                       ptr = _tcsstr(urlComponents.lpszUrlPath, _T("/tags"));\r
+                                       if (ptr == NULL)\r
+                                               ptr = _tcsstr(urlComponents.lpszUrlPath, _T("\\tags"));\r
+                                       if ((ptr)&&(*(ptr+5) != 0)&&(*(ptr+5) != '/')&&(*(ptr+5) != '\\'))\r
+                                               ptr = NULL;\r
+                               }\r
+                       }\r
+                       if (ptr)\r
+                               itemshorturl = ptr;\r
+                       else\r
+                               itemshorturl = urlComponents.lpszUrlPath;\r
+               }\r
+               else \r
+                       itemshorturl = _T(" ");\r
+       }\r
+       else\r
+               itemshorturl = _T(" ");\r
+\r
+       if (status)\r
+       {\r
+               char url[INTERNET_MAX_URL_LENGTH];\r
+               strcpy_s(url, INTERNET_MAX_URL_LENGTH, status->url);\r
+               CPathUtils::Unescape(url);\r
+               itemurl = UTF8ToWide(url);\r
+       }\r
+       else if (t == ShellCache::exe)\r
+       {\r
+               char url[INTERNET_MAX_URL_LENGTH];\r
+               strcpy_s(url, INTERNET_MAX_URL_LENGTH, itemStatus.m_url);\r
+               CPathUtils::Unescape(url);\r
+               itemurl = UTF8ToWide(url);\r
+       }\r
+}\r
+\r
diff --git a/TortoiseShell/ContextMenu.cpp b/TortoiseShell/ContextMenu.cpp
new file mode 100644 (file)
index 0000000..bf98b69
--- /dev/null
@@ -0,0 +1,2403 @@
+// TortoiseSVN - a Windows shell extension for easy version control\r
+\r
+// Copyright (C) 2003-2008 - TortoiseSVN\r
+\r
+// This program is free software; you can redistribute it and/or\r
+// modify it under the terms of the GNU General Public License\r
+// as published by the Free Software Foundation; either version 2\r
+// of the License, or (at your option) any later version.\r
+\r
+// This program is distributed in the hope that it will be useful,\r
+// but WITHOUT ANY WARRANTY; without even the implied warranty of\r
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\r
+// GNU General Public License for more details.\r
+\r
+// You should have received a copy of the GNU General Public License\r
+// along with this program; if not, write to the Free Software Foundation,\r
+// 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.\r
+//\r
+#include "stdafx.h"\r
+#include "ShellExt.h"\r
+#include "ItemIDList.h"\r
+#include "PreserveChdir.h"\r
+#include "UnicodeUtils.h"\r
+#include "SVNProperties.h"\r
+#include "SVNStatus.h"\r
+\r
+#define GetPIDLFolder(pida) (LPCITEMIDLIST)(((LPBYTE)pida)+(pida)->aoffset[0])\r
+#define GetPIDLItem(pida, i) (LPCITEMIDLIST)(((LPBYTE)pida)+(pida)->aoffset[i+1])\r
+\r
+int g_shellidlist=RegisterClipboardFormat(CFSTR_SHELLIDLIST);\r
+\r
+CShellExt::MenuInfo CShellExt::menuInfo[] =\r
+{\r
+       { ShellMenuCheckout,                                    MENUCHECKOUT,           IDI_CHECKOUT,                   IDS_MENUCHECKOUT,                       IDS_MENUDESCCHECKOUT,\r
+       ITEMIS_FOLDER, ITEMIS_INSVN|ITEMIS_FOLDERINSVN, 0, 0, 0, 0, 0, 0 },\r
+\r
+       { ShellMenuUpdate,                                              MENUUPDATE,                     IDI_UPDATE,                             IDS_MENUUPDATE,                         IDS_MENUDESCUPDATE,                             \r
+       ITEMIS_INSVN,   ITEMIS_ADDED, ITEMIS_FOLDERINSVN, 0, 0, 0, 0, 0 },\r
+\r
+       { ShellMenuCommit,                                              MENUCOMMIT,                     IDI_COMMIT,                             IDS_MENUCOMMIT,                         IDS_MENUDESCCOMMIT,\r
+       ITEMIS_INSVN, 0, ITEMIS_FOLDERINSVN, 0, 0, 0, 0, 0 },\r
+\r
+       { ShellSeparator, 0, 0, 0, 0, 0, 0, 0, 0},\r
+\r
+       { ShellMenuDiff,                                                MENUDIFF,                       IDI_DIFF,                               IDS_MENUDIFF,                           IDS_MENUDESCDIFF,\r
+       ITEMIS_INSVN|ITEMIS_ONLYONE, ITEMIS_FOLDER|ITEMIS_NORMAL, ITEMIS_TWO, 0, 0, 0, 0, 0 },\r
+\r
+       { ShellMenuPrevDiff,                                    MENUPREVDIFF,                   IDI_DIFF,                               IDS_MENUPREVDIFF,                       IDS_MENUDESCPREVDIFF,\r
+       ITEMIS_INSVN|ITEMIS_ONLYONE, ITEMIS_FOLDER, 0, 0, 0, 0, 0, 0 },\r
+\r
+       { ShellMenuUrlDiff,                                             MENUURLDIFF,            IDI_DIFF,                               IDS_MENUURLDIFF,                        IDS_MENUDESCURLDIFF,\r
+       ITEMIS_INSVN|ITEMIS_ONLYONE|ITEMIS_EXTENDED, 0, ITEMIS_FOLDERINSVN|ITEMIS_EXTENDED|ITEMIS_ONLYONE, 0, 0, 0, 0, 0 },\r
+\r
+       { ShellMenuLog,                                                 MENULOG,                        IDI_LOG,                                IDS_MENULOG,                            IDS_MENUDESCLOG,\r
+       ITEMIS_INSVN|ITEMIS_ONLYONE, ITEMIS_ADDED, ITEMIS_FOLDER|ITEMIS_FOLDERINSVN|ITEMIS_ONLYONE, ITEMIS_ADDED, ITEMIS_FOLDERINSVN|ITEMIS_ONLYONE, ITEMIS_ADDED, 0, 0 },\r
+\r
+       { ShellMenuRepoBrowse,                                  MENUREPOBROWSE,         IDI_REPOBROWSE,                 IDS_MENUREPOBROWSE,                     IDS_MENUDESCREPOBROWSE,\r
+       ITEMIS_ONLYONE, 0, ITEMIS_FOLDERINSVN|ITEMIS_ONLYONE, 0, 0, 0, 0, 0 },\r
+\r
+       { ShellMenuShowChanged,                                 MENUSHOWCHANGED,        IDI_SHOWCHANGED,                IDS_MENUSHOWCHANGED,            IDS_MENUDESCSHOWCHANGED,\r
+       ITEMIS_INSVN|ITEMIS_ONLYONE, 0, ITEMIS_FOLDER|ITEMIS_FOLDERINSVN|ITEMIS_ONLYONE, 0, 0, 0, 0, 0},\r
+\r
+       { ShellMenuRevisionGraph,                               MENUREVISIONGRAPH,      IDI_REVISIONGRAPH,              IDS_MENUREVISIONGRAPH,          IDS_MENUDESCREVISIONGRAPH,\r
+       ITEMIS_INSVN|ITEMIS_ONLYONE, ITEMIS_ADDED, ITEMIS_FOLDER|ITEMIS_FOLDERINSVN|ITEMIS_ONLYONE, ITEMIS_ADDED, 0, 0, 0, 0},\r
+\r
+       { ShellSeparator, 0, 0, 0, 0, 0, 0, 0, 0},\r
+\r
+       { ShellMenuConflictEditor,                              MENUCONFLICTEDITOR,     IDI_CONFLICT,                   IDS_MENUCONFLICT,                       IDS_MENUDESCCONFLICT,\r
+       ITEMIS_INSVN|ITEMIS_CONFLICTED, ITEMIS_FOLDER, 0, 0, 0, 0, 0, 0 },\r
+\r
+       { ShellMenuResolve,                                             MENURESOLVE,            IDI_RESOLVE,                    IDS_MENURESOLVE,                        IDS_MENUDESCRESOLVE,\r
+       ITEMIS_INSVN|ITEMIS_CONFLICTED, 0, ITEMIS_INSVN|ITEMIS_FOLDER, 0, ITEMIS_FOLDERINSVN, 0, 0, 0 },\r
+\r
+       { ShellMenuUpdateExt,                                   MENUUPDATEEXT,          IDI_UPDATE,                             IDS_MENUUPDATEEXT,                      IDS_MENUDESCUPDATEEXT,\r
+       ITEMIS_INSVN, ITEMIS_ADDED, ITEMIS_FOLDERINSVN, ITEMIS_ADDED, 0, 0, 0, 0 },\r
+\r
+       { ShellMenuRename,                                              MENURENAME,                     IDI_RENAME,                             IDS_MENURENAME,                         IDS_MENUDESCRENAME,\r
+       ITEMIS_INSVN|ITEMIS_ONLYONE|ITEMIS_INVERSIONEDFOLDER, 0, 0, 0, 0, 0, 0, 0 },\r
+\r
+       { ShellMenuRemove,                                              MENUREMOVE,                     IDI_DELETE,                             IDS_MENUREMOVE,                         IDS_MENUDESCREMOVE,\r
+       ITEMIS_INSVN|ITEMIS_INVERSIONEDFOLDER, ITEMIS_ADDED, 0, 0, 0, 0, 0, 0 },\r
+\r
+       { ShellMenuRemoveKeep,                                  MENUREMOVE,                     IDI_DELETE,                             IDS_MENUREMOVEKEEP,                     IDS_MENUDESCREMOVEKEEP,\r
+       ITEMIS_INSVN|ITEMIS_INVERSIONEDFOLDER|ITEMIS_EXTENDED, ITEMIS_ADDED, 0, 0, 0, 0, 0, 0 },\r
+\r
+       { ShellMenuRevert,                                              MENUREVERT,                     IDI_REVERT,                             IDS_MENUREVERT,                         IDS_MENUDESCREVERT,\r
+       ITEMIS_INSVN, ITEMIS_NORMAL|ITEMIS_ADDED, ITEMIS_FOLDERINSVN, ITEMIS_ADDED, 0, 0, 0, 0 },\r
+\r
+       { ShellMenuRevert,                                              MENUREVERT,                     IDI_REVERT,                             IDS_MENUUNDOADD,                        IDS_MENUDESCUNDOADD,\r
+       ITEMIS_ADDED, ITEMIS_NORMAL, ITEMIS_FOLDERINSVN|ITEMIS_ADDED, 0, 0, 0, 0, 0 },\r
+\r
+       { ShellMenuDelUnversioned,                              MENUDELUNVERSIONED,     IDI_DELUNVERSIONED,             IDS_MENUDELUNVERSIONED,         IDS_MENUDESCDELUNVERSIONED,\r
+       ITEMIS_FOLDER|ITEMIS_INSVN|ITEMIS_EXTENDED, 0, ITEMIS_FOLDER|ITEMIS_FOLDERINSVN|ITEMIS_EXTENDED, 0, 0, 0, 0, 0 },\r
+\r
+       { ShellMenuCleanup,                                             MENUCLEANUP,            IDI_CLEANUP,                    IDS_MENUCLEANUP,                        IDS_MENUDESCCLEANUP,\r
+       ITEMIS_INSVN|ITEMIS_FOLDER, 0, ITEMIS_FOLDERINSVN|ITEMIS_FOLDER, 0, 0, 0, 0, 0 },\r
+\r
+       { ShellMenuLock,                                                MENULOCK,                       IDI_LOCK,                               IDS_MENU_LOCK,                          IDS_MENUDESC_LOCK,\r
+       ITEMIS_INSVN, ITEMIS_LOCKED|ITEMIS_ADDED, ITEMIS_FOLDERINSVN, ITEMIS_LOCKED|ITEMIS_ADDED, 0, 0, 0, 0 },\r
+\r
+       { ShellMenuUnlock,                                              MENUUNLOCK,                     IDI_UNLOCK,                             IDS_MENU_UNLOCK,                        IDS_MENUDESC_UNLOCK,\r
+       ITEMIS_INSVN|ITEMIS_LOCKED, 0, ITEMIS_FOLDER|ITEMIS_INSVN, 0, ITEMIS_FOLDERINSVN, 0, 0, 0 },\r
+\r
+       { ShellMenuUnlockForce,                                 MENUUNLOCK,                     IDI_UNLOCK,                             IDS_MENU_UNLOCKFORCE,           IDS_MENUDESC_UNLOCKFORCE,\r
+       ITEMIS_INSVN|ITEMIS_LOCKED, 0, ITEMIS_FOLDER|ITEMIS_INSVN|ITEMIS_EXTENDED, 0, 0, 0, 0, 0 },\r
+\r
+       { ShellSeparator, 0, 0, 0, 0, 0, 0, 0, 0},\r
+\r
+       { ShellMenuCopy,                                                MENUCOPY,                       IDI_COPY,                               IDS_MENUBRANCH,                         IDS_MENUDESCCOPY,\r
+       ITEMIS_INSVN|ITEMIS_ONLYONE, ITEMIS_ADDED, ITEMIS_FOLDER|ITEMIS_FOLDERINSVN|ITEMIS_ONLYONE, 0, 0, 0, 0, 0 },\r
+\r
+       { ShellMenuSwitch,                                              MENUSWITCH,                     IDI_SWITCH,                             IDS_MENUSWITCH,                         IDS_MENUDESCSWITCH,\r
+       ITEMIS_INSVN|ITEMIS_ONLYONE, ITEMIS_ADDED, ITEMIS_FOLDER|ITEMIS_FOLDERINSVN|ITEMIS_ONLYONE, 0, 0, 0, 0, 0 },\r
+\r
+       { ShellMenuMerge,                                               MENUMERGE,                      IDI_MERGE,                              IDS_MENUMERGE,                          IDS_MENUDESCMERGE,\r
+       ITEMIS_INSVN|ITEMIS_ONLYONE, ITEMIS_ADDED, ITEMIS_FOLDER|ITEMIS_FOLDERINSVN|ITEMIS_ONLYONE, 0, 0, 0, 0, 0 },\r
+       { ShellMenuMergeAll,                                    MENUMERGEALL,           IDI_MERGE,                              IDS_MENUMERGEALL,                       IDS_MENUDESCMERGEALL,\r
+       ITEMIS_INSVN|ITEMIS_ONLYONE|ITEMIS_EXTENDED, ITEMIS_ADDED, ITEMIS_FOLDER|ITEMIS_FOLDERINSVN|ITEMIS_ONLYONE|ITEMIS_EXTENDED, 0, 0, 0, 0, 0 },\r
+\r
+       { ShellMenuExport,                                              MENUEXPORT,                     IDI_EXPORT,                             IDS_MENUEXPORT,                         IDS_MENUDESCEXPORT,\r
+       ITEMIS_FOLDER|ITEMIS_ONLYONE, 0, 0, 0, 0, 0, 0, 0 },\r
+\r
+       { ShellMenuRelocate,                                    MENURELOCATE,           IDI_RELOCATE,                   IDS_MENURELOCATE,                       IDS_MENUDESCRELOCATE,\r
+       ITEMIS_INSVN|ITEMIS_FOLDER|ITEMIS_FOLDERINSVN|ITEMIS_ONLYONE, 0, ITEMIS_FOLDERINSVN|ITEMIS_ONLYONE, 0, 0, 0, 0, 0 },\r
+\r
+       { ShellSeparator, 0, 0, 0, 0, 0, 0, 0, 0},\r
+\r
+       { ShellMenuCreateRepos,                                 MENUCREATEREPOS,        IDI_CREATEREPOS,                IDS_MENUCREATEREPOS,            IDS_MENUDESCCREATEREPOS,\r
+       ITEMIS_FOLDER, ITEMIS_INSVN|ITEMIS_FOLDERINSVN, 0, 0, 0, 0, 0, 0 },\r
+\r
+       { ShellMenuAdd,                                                 MENUADD,                        IDI_ADD,                                IDS_MENUADD,                            IDS_MENUDESCADD,\r
+       ITEMIS_INVERSIONEDFOLDER, ITEMIS_INSVN, ITEMIS_INSVN|ITEMIS_FOLDER, 0, ITEMIS_IGNORED, 0, ITEMIS_DELETED, ITEMIS_FOLDER|ITEMIS_ONLYONE },\r
+\r
+       { ShellMenuAddAsReplacement,                    MENUADD,                        IDI_ADD,                                IDS_MENUADDASREPLACEMENT,       IDS_MENUADDASREPLACEMENT,\r
+       ITEMIS_DELETED|ITEMIS_ONLYONE, ITEMIS_FOLDER, 0, 0, 0, 0, 0, 0 },\r
+\r
+       { ShellMenuImport,                                              MENUIMPORT,                     IDI_IMPORT,                             IDS_MENUIMPORT,                         IDS_MENUDESCIMPORT,\r
+       ITEMIS_FOLDER, ITEMIS_INSVN, 0, 0, 0, 0, 0, 0 },\r
+\r
+       { ShellMenuBlame,                                               MENUBLAME,                      IDI_BLAME,                              IDS_MENUBLAME,                          IDS_MENUDESCBLAME,\r
+       ITEMIS_INSVN|ITEMIS_ONLYONE, ITEMIS_FOLDER|ITEMIS_ADDED, 0, 0, 0, 0, 0, 0 },\r
+\r
+       { ShellMenuIgnoreSub,                                   MENUIGNORE,                     IDI_IGNORE,                             IDS_MENUIGNORE,                         IDS_MENUDESCIGNORE,\r
+       ITEMIS_INVERSIONEDFOLDER, ITEMIS_IGNORED|ITEMIS_INSVN, 0, 0, 0, 0, 0, 0 },\r
+\r
+       { ShellMenuUnIgnoreSub,                                 MENUIGNORE,                     IDI_IGNORE,                             IDS_MENUUNIGNORE,                       IDS_MENUDESCUNIGNORE,\r
+       ITEMIS_IGNORED, 0, 0, 0, 0, 0, 0, 0 },\r
+\r
+       { ShellSeparator, 0, 0, 0, 0, 0, 0, 0, 0},\r
+\r
+       { ShellMenuCreatePatch,                                 MENUCREATEPATCH,        IDI_CREATEPATCH,                IDS_MENUCREATEPATCH,            IDS_MENUDESCCREATEPATCH,\r
+       ITEMIS_INSVN, ITEMIS_NORMAL, ITEMIS_FOLDERINSVN, 0, 0, 0, 0, 0 },\r
+\r
+       { ShellMenuApplyPatch,                                  MENUAPPLYPATCH,         IDI_PATCH,                              IDS_MENUAPPLYPATCH,                     IDS_MENUDESCAPPLYPATCH,\r
+       ITEMIS_INSVN|ITEMIS_FOLDER|ITEMIS_FOLDERINSVN, ITEMIS_ADDED, ITEMIS_ONLYONE|ITEMIS_PATCHFILE, 0, ITEMIS_FOLDERINSVN, ITEMIS_ADDED, 0, 0 },\r
+\r
+       { ShellMenuProperties,                                  MENUPROPERTIES,         IDI_PROPERTIES,                 IDS_MENUPROPERTIES,                     IDS_MENUDESCPROPERTIES,\r
+       ITEMIS_INSVN, 0, ITEMIS_FOLDERINSVN, 0, 0, 0, 0, 0 },\r
+\r
+       { ShellSeparator, 0, 0, 0, 0, 0, 0, 0, 0},\r
+       { ShellMenuClipPaste,                                   MENUCLIPPASTE,          IDI_CLIPPASTE,                  IDS_MENUCLIPPASTE,                      IDS_MENUDESCCLIPPASTE,\r
+       ITEMIS_INSVN|ITEMIS_FOLDER|ITEMIS_PATHINCLIPBOARD, 0, 0, 0, 0, 0, 0, 0 },\r
+\r
+       { ShellSeparator, 0, 0, 0, 0, 0, 0, 0, 0},\r
+\r
+       { ShellMenuSettings,                                    MENUSETTINGS,           IDI_SETTINGS,                   IDS_MENUSETTINGS,                       IDS_MENUDESCSETTINGS,\r
+       ITEMIS_FOLDER, 0, 0, ITEMIS_FOLDER, 0, 0, 0, 0 },\r
+       { ShellMenuHelp,                                                MENUHELP,                       IDI_HELP,                               IDS_MENUHELP,                           IDS_MENUDESCHELP,\r
+       ITEMIS_FOLDER, 0, 0, ITEMIS_FOLDER, 0, 0, 0, 0 },\r
+       { ShellMenuAbout,                                               MENUABOUT,                      IDI_ABOUT,                              IDS_MENUABOUT,                          IDS_MENUDESCABOUT,\r
+       ITEMIS_FOLDER, 0, 0, ITEMIS_FOLDER, 0, 0, 0, 0 },\r
+\r
+       // the sub menus - they're not added like the the commands, therefore the menu ID is zero\r
+       // but they still need to be in here, because we use the icon and string information anyway.\r
+       { ShellSubMenu,                                                 NULL,                           IDI_APP,                                IDS_MENUSUBMENU,                        0,\r
+       0, 0, 0, 0, 0, 0, 0, 0 },\r
+       { ShellSubMenuFile,                                             NULL,                           IDI_MENUFILE,                   IDS_MENUSUBMENU,                        0,\r
+       0, 0, 0, 0, 0, 0, 0, 0 },\r
+       { ShellSubMenuFolder,                                   NULL,                           IDI_MENUFOLDER,                 IDS_MENUSUBMENU,                        0,\r
+       0, 0, 0, 0, 0, 0, 0, 0 },\r
+       { ShellSubMenuLink,                                             NULL,                           IDI_MENULINK,                   IDS_MENUSUBMENU,                        0,\r
+       0, 0, 0, 0, 0, 0, 0, 0 },\r
+       { ShellSubMenuMultiple,                                 NULL,                           IDI_MENUMULTIPLE,               IDS_MENUSUBMENU,                        0,\r
+       0, 0, 0, 0, 0, 0, 0, 0 },\r
+       // mark the last entry to tell the loop where to stop iterating over this array\r
+       { ShellMenuLastEntry,                                   0,                                      0,                                              0,                                                      0,\r
+       0, 0, 0, 0, 0, 0, 0, 0 },\r
+};\r
+\r
+\r
+STDMETHODIMP CShellExt::Initialize(LPCITEMIDLIST pIDFolder,\r
+                                   LPDATAOBJECT pDataObj,\r
+                                   HKEY /* hRegKey */)\r
+{\r
+       ATLTRACE("Shell :: Initialize\n");\r
+       PreserveChdir preserveChdir;\r
+       files_.clear();\r
+       folder_.erase();\r
+       uuidSource.erase();\r
+       uuidTarget.erase();\r
+       itemStates = 0;\r
+       itemStatesFolder = 0;\r
+       stdstring statuspath;\r
+       svn_wc_status_kind fetchedstatus = svn_wc_status_none;\r
+       // get selected files/folders\r
+       if (pDataObj)\r
+       {\r
+               STGMEDIUM medium;\r
+               FORMATETC fmte = {(CLIPFORMAT)g_shellidlist,\r
+                       (DVTARGETDEVICE FAR *)NULL, \r
+                       DVASPECT_CONTENT, \r
+                       -1, \r
+                       TYMED_HGLOBAL};\r
+               HRESULT hres = pDataObj->GetData(&fmte, &medium);\r
+\r
+               if (SUCCEEDED(hres) && medium.hGlobal)\r
+               {\r
+                       if (m_State == FileStateDropHandler)\r
+                       {\r
+                               FORMATETC etc = { CF_HDROP, NULL, DVASPECT_CONTENT, -1, TYMED_HGLOBAL };\r
+                               STGMEDIUM stg = { TYMED_HGLOBAL };\r
+                               if ( FAILED( pDataObj->GetData ( &etc, &stg )))\r
+                               {\r
+                                       ReleaseStgMedium ( &medium );\r
+                                       return E_INVALIDARG;\r
+                               }\r
+\r
+\r
+                               HDROP drop = (HDROP)GlobalLock(stg.hGlobal);\r
+                               if ( NULL == drop )\r
+                               {\r
+                                       ReleaseStgMedium ( &stg );\r
+                                       ReleaseStgMedium ( &medium );\r
+                                       return E_INVALIDARG;\r
+                               }\r
+\r
+                               int count = DragQueryFile(drop, (UINT)-1, NULL, 0);\r
+                               if (count == 1)\r
+                                       itemStates |= ITEMIS_ONLYONE;\r
+                               for (int i = 0; i < count; i++)\r
+                               {\r
+                                       // find the path length in chars\r
+                                       UINT len = DragQueryFile(drop, i, NULL, 0);\r
+                                       if (len == 0)\r
+                                               continue;\r
+                                       TCHAR * szFileName = new TCHAR[len+1];\r
+                                       if (0 == DragQueryFile(drop, i, szFileName, len+1))\r
+                                       {\r
+                                               delete [] szFileName;\r
+                                               continue;\r
+                                       }\r
+                                       stdstring str = stdstring(szFileName);\r
+                                       delete [] szFileName;\r
+                                       if ((str.empty() == false)&&(g_ShellCache.IsContextPathAllowed(szFileName)))\r
+                                       {\r
+                                               if (itemStates & ITEMIS_ONLYONE)\r
+                                               {\r
+                                                       CTSVNPath strpath;\r
+                                                       strpath.SetFromWin(str.c_str());\r
+                                                       itemStates |= (strpath.GetFileExtension().CompareNoCase(_T(".diff"))==0) ? ITEMIS_PATCHFILE : 0;\r
+                                                       itemStates |= (strpath.GetFileExtension().CompareNoCase(_T(".patch"))==0) ? ITEMIS_PATCHFILE : 0;\r
+                                               }\r
+                                               files_.push_back(str);\r
+                                               if (i == 0)\r
+                                               {\r
+                                                       //get the Subversion status of the item\r
+                                                       svn_wc_status_kind status = svn_wc_status_none;\r
+                                                       CTSVNPath askedpath;\r
+                                                       askedpath.SetFromWin(str.c_str());\r
+                                                       try\r
+                                                       {\r
+                                                               SVNStatus stat;\r
+                                                               stat.GetStatus(CTSVNPath(str.c_str()), false, true, true);\r
+                                                               if (stat.status)\r
+                                                               {\r
+                                                                       statuspath = str;\r
+                                                                       status = SVNStatus::GetMoreImportant(stat.status->text_status, stat.status->prop_status);\r
+                                                                       fetchedstatus = status;\r
+                                                                       if ((stat.status->entry)&&(stat.status->entry->lock_token))\r
+                                                                               itemStates |= (stat.status->entry->lock_token[0] != 0) ? ITEMIS_LOCKED : 0;\r
+                                                                       if ((stat.status->entry)&&(stat.status->entry->kind == svn_node_dir))\r
+                                                                       {\r
+                                                                               itemStates |= ITEMIS_FOLDER;\r
+                                                                               if ((status != svn_wc_status_unversioned)&&(status != svn_wc_status_ignored)&&(status != svn_wc_status_none))\r
+                                                                                       itemStates |= ITEMIS_FOLDERINSVN;\r
+                                                                       }\r
+                                                                       if ((stat.status->entry)&&(stat.status->entry->present_props))\r
+                                                                       {\r
+                                                                               if (strstr(stat.status->entry->present_props, "svn:needs-lock"))\r
+                                                                                       itemStates |= ITEMIS_NEEDSLOCK;\r
+                                                                       }\r
+                                                                       if ((stat.status->entry)&&(stat.status->entry->uuid))\r
+                                                                               uuidSource = CUnicodeUtils::StdGetUnicode(stat.status->entry->uuid);\r
+                                                               }\r
+                                                               else\r
+                                                               {\r
+                                                                       // sometimes, svn_client_status() returns with an error.\r
+                                                                       // in that case, we have to check if the working copy is versioned\r
+                                                                       // anyway to show the 'correct' context menu\r
+                                                                       if (askedpath.HasAdminDir())\r
+                                                                               status = svn_wc_status_normal;\r
+                                                               }\r
+                                                       }\r
+                                                       catch ( ... )\r
+                                                       {\r
+                                                               ATLTRACE2(_T("Exception in SVNStatus::GetAllStatus()\n"));\r
+                                                       }\r
+                                                       if ((status != svn_wc_status_unversioned)&&(status != svn_wc_status_ignored)&&(status != svn_wc_status_none))\r
+                                                               itemStates |= ITEMIS_INSVN;\r
+                                                       if (status == svn_wc_status_ignored)\r
+                                                               itemStates |= ITEMIS_IGNORED;\r
+                                                       if (status == svn_wc_status_normal)\r
+                                                               itemStates |= ITEMIS_NORMAL;\r
+                                                       if (status == svn_wc_status_conflicted)\r
+                                                               itemStates |= ITEMIS_CONFLICTED;\r
+                                                       if (status == svn_wc_status_added)\r
+                                                               itemStates |= ITEMIS_ADDED;\r
+                                                       if (status == svn_wc_status_deleted)\r
+                                                               itemStates |= ITEMIS_DELETED;\r
+                                               }\r
+                                       }\r
+                               } // for (int i = 0; i < count; i++)\r
+                               GlobalUnlock ( drop );\r
+                               ReleaseStgMedium ( &stg );\r
+                       } // if (m_State == FileStateDropHandler) \r
+                       else\r
+                       {\r
+                               //Enumerate PIDLs which the user has selected\r
+                               CIDA* cida = (CIDA*)GlobalLock(medium.hGlobal);\r
+                               ItemIDList parent( GetPIDLFolder (cida));\r
+\r
+                               int count = cida->cidl;\r
+                               BOOL statfetched = FALSE;\r
+                               for (int i = 0; i < count; ++i)\r
+                               {\r
+                                       ItemIDList child (GetPIDLItem (cida, i), &parent);\r
+                                       stdstring str = child.toString();\r
+                                       if ((str.empty() == false)&&(g_ShellCache.IsContextPathAllowed(str.c_str())))\r
+                                       {\r
+                                               //check if our menu is requested for a subversion admin directory\r
+                                               if (g_SVNAdminDir.IsAdminDirPath(str.c_str()))\r
+                                                       continue;\r
+\r
+                                               files_.push_back(str);\r
+                                               CTSVNPath strpath;\r
+                                               strpath.SetFromWin(str.c_str());\r
+                                               itemStates |= (strpath.GetFileExtension().CompareNoCase(_T(".diff"))==0) ? ITEMIS_PATCHFILE : 0;\r
+                                               itemStates |= (strpath.GetFileExtension().CompareNoCase(_T(".patch"))==0) ? ITEMIS_PATCHFILE : 0;\r
+                                               if (!statfetched)\r
+                                               {\r
+                                                       //get the Subversion status of the item\r
+                                                       svn_wc_status_kind status = svn_wc_status_none;\r
+                                                       if ((g_ShellCache.IsSimpleContext())&&(strpath.IsDirectory()))\r
+                                                       {\r
+                                                               if (strpath.HasAdminDir())\r
+                                                                       status = svn_wc_status_normal;\r
+                                                       }\r
+                                                       else\r
+                                                       {\r
+                                                               try\r
+                                                               {\r
+                                                                       SVNStatus stat;\r
+                                                                       if (strpath.HasAdminDir())\r
+                                                                               stat.GetStatus(strpath, false, true, true);\r
+                                                                       statuspath = str;\r
+                                                                       if (stat.status)\r
+                                                                       {\r
+                                                                               status = SVNStatus::GetMoreImportant(stat.status->text_status, stat.status->prop_status);\r
+                                                                               fetchedstatus = status;\r
+                                                                               if ((stat.status->entry)&&(stat.status->entry->lock_token))\r
+                                                                                       itemStates |= (stat.status->entry->lock_token[0] != 0) ? ITEMIS_LOCKED : 0;\r
+                                                                               if ((stat.status->entry)&&(stat.status->entry->kind == svn_node_dir))\r
+                                                                               {\r
+                                                                                       itemStates |= ITEMIS_FOLDER;\r
+                                                                                       if ((status != svn_wc_status_unversioned)&&(status != svn_wc_status_ignored)&&(status != svn_wc_status_none))\r
+                                                                                               itemStates |= ITEMIS_FOLDERINSVN;\r
+                                                                               }\r
+                                                                               if ((stat.status->entry)&&(stat.status->entry->conflict_wrk))\r
+                                                                                       itemStates |= ITEMIS_CONFLICTED;\r
+                                                                               if ((stat.status->entry)&&(stat.status->entry->present_props))\r
+                                                                               {\r
+                                                                                       if (strstr(stat.status->entry->present_props, "svn:needs-lock"))\r
+                                                                                               itemStates |= ITEMIS_NEEDSLOCK;\r
+                                                                               }\r
+                                                                               if ((stat.status->entry)&&(stat.status->entry->uuid))\r
+                                                                                       uuidSource = CUnicodeUtils::StdGetUnicode(stat.status->entry->uuid);\r
+                                                                       }       \r
+                                                                       else\r
+                                                                       {\r
+                                                                               // sometimes, svn_client_status() returns with an error.\r
+                                                                               // in that case, we have to check if the working copy is versioned\r
+                                                                               // anyway to show the 'correct' context menu\r
+                                                                               if (strpath.HasAdminDir())\r
+                                                                               {\r
+                                                                                       status = svn_wc_status_normal;\r
+                                                                                       fetchedstatus = status;\r
+                                                                               }\r
+                                                                       }\r
+                                                                       statfetched = TRUE;\r
+                                                               }\r
+                                                               catch ( ... )\r
+                                                               {\r
+                                                                       ATLTRACE2(_T("Exception in SVNStatus::GetAllStatus()\n"));\r
+                                                               }\r
+                                                       }\r
+                                                       if ((status != svn_wc_status_unversioned)&&(status != svn_wc_status_ignored)&&(status != svn_wc_status_none))\r
+                                                               itemStates |= ITEMIS_INSVN;\r
+                                                       if (status == svn_wc_status_ignored)\r
+                                                       {\r
+                                                               itemStates |= ITEMIS_IGNORED;\r
+                                                               // the item is ignored. Get the svn:ignored properties so we can (maybe) later\r
+                                                               // offer a 'remove from ignored list' entry\r
+                                                               SVNProperties props(strpath.GetContainingDirectory(), false);\r
+                                                               ignoredprops.empty();\r
+                                                               for (int p=0; p<props.GetCount(); ++p)\r
+                                                               {\r
+                                                                       if (props.GetItemName(p).compare(stdstring(_T("svn:ignore")))==0)\r
+                                                                       {\r
+                                                                               std::string st = props.GetItemValue(p);\r
+                                                                               ignoredprops = MultibyteToWide(st.c_str());\r
+                                                                               // remove all escape chars ('\\')\r
+                                                                               std::remove(ignoredprops.begin(), ignoredprops.end(), '\\');\r
+                                                                               break;\r
+                                                                       }\r
+                                                               }\r
+                                                       }\r
+                                                       if (status == svn_wc_status_normal)\r
+                                                               itemStates |= ITEMIS_NORMAL;\r
+                                                       if (status == svn_wc_status_conflicted)\r
+                                                               itemStates |= ITEMIS_CONFLICTED;\r
+                                                       if (status == svn_wc_status_added)\r
+                                                               itemStates |= ITEMIS_ADDED;\r
+                                                       if (status == svn_wc_status_deleted)\r
+                                                               itemStates |= ITEMIS_DELETED;\r
+                                               }\r
+                                       }\r
+                               } // for (int i = 0; i < count; ++i)\r
+                               ItemIDList child (GetPIDLItem (cida, 0), &parent);\r
+                               if (g_ShellCache.HasSVNAdminDir(child.toString().c_str(), FALSE))\r
+                                       itemStates |= ITEMIS_INVERSIONEDFOLDER;\r
+                               GlobalUnlock(medium.hGlobal);\r
+\r
+                               // if the item is a versioned folder, check if there's a patch file\r
+                               // in the clipboard to be used in "Apply Patch"\r
+                               UINT cFormatDiff = RegisterClipboardFormat(_T("TSVN_UNIFIEDDIFF"));\r
+                               if (cFormatDiff)\r
+                               {\r
+                                       if (IsClipboardFormatAvailable(cFormatDiff)) \r
+                                               itemStates |= ITEMIS_PATCHINCLIPBOARD;\r
+                               }\r
+                               if (IsClipboardFormatAvailable(CF_HDROP)) \r
+                                       itemStates |= ITEMIS_PATHINCLIPBOARD;\r
+                       }\r
+\r
+                       ReleaseStgMedium ( &medium );\r
+                       if (medium.pUnkForRelease)\r
+                       {\r
+                               IUnknown* relInterface = (IUnknown*)medium.pUnkForRelease;\r
+                               relInterface->Release();\r
+                       }\r
+               }\r
+       }\r
+\r
+       // get folder background\r
+       if (pIDFolder)\r
+       {\r
+               ItemIDList list(pIDFolder);\r
+               folder_ = list.toString();\r
+               svn_wc_status_kind status = svn_wc_status_none;\r
+               if (IsClipboardFormatAvailable(CF_HDROP)) \r
+                       itemStatesFolder |= ITEMIS_PATHINCLIPBOARD;\r
+               if ((folder_.compare(statuspath)!=0)&&(g_ShellCache.IsContextPathAllowed(folder_.c_str())))\r
+               {\r
+                       CTSVNPath askedpath;\r
+                       askedpath.SetFromWin(folder_.c_str());\r
+                       try\r
+                       {\r
+                               SVNStatus stat;\r
+                               stat.GetStatus(CTSVNPath(folder_.c_str()), false, true, true);\r
+                               if (stat.status)\r
+                               {\r
+                                       status = SVNStatus::GetMoreImportant(stat.status->text_status, stat.status->prop_status);\r
+                                       if ((stat.status->entry)&&(stat.status->entry->lock_token))\r
+                                               itemStatesFolder |= (stat.status->entry->lock_token[0] != 0) ? ITEMIS_LOCKED : 0;\r
+                                       if ((stat.status->entry)&&(stat.status->entry->present_props))\r
+                                       {\r
+                                               if (strstr(stat.status->entry->present_props, "svn:needs-lock"))\r
+                                                       itemStatesFolder |= ITEMIS_NEEDSLOCK;\r
+                                       }\r
+                                       if ((stat.status->entry)&&(stat.status->entry->uuid))\r
+                                               uuidTarget = CUnicodeUtils::StdGetUnicode(stat.status->entry->uuid);\r
+                                       if ((status != svn_wc_status_unversioned)&&(status != svn_wc_status_ignored)&&(status != svn_wc_status_none))\r
+                                               itemStatesFolder |= ITEMIS_INSVN;\r
+                                       if (status == svn_wc_status_normal)\r
+                                               itemStatesFolder |= ITEMIS_NORMAL;\r
+                                       if (status == svn_wc_status_conflicted)\r
+                                               itemStatesFolder |= ITEMIS_CONFLICTED;\r
+                                       if (status == svn_wc_status_added)\r
+                                               itemStatesFolder |= ITEMIS_ADDED;\r
+                                       if (status == svn_wc_status_deleted)\r
+                                               itemStatesFolder |= ITEMIS_DELETED;\r
+                               }\r
+                               else\r
+                               {\r
+                                       // sometimes, svn_client_status() returns with an error.\r
+                                       // in that case, we have to check if the working copy is versioned\r
+                                       // anyway to show the 'correct' context menu\r
+                                       if (askedpath.HasAdminDir())\r
+                                               status = svn_wc_status_normal;\r
+                               }\r
+                       }\r
+                       catch ( ... )\r
+                       {\r
+                               ATLTRACE2(_T("Exception in SVNStatus::GetAllStatus()\n"));\r
+                       }\r
+               }\r
+               else\r
+               {\r
+                       status = fetchedstatus;\r
+               }\r
+               if ((status != svn_wc_status_unversioned)&&(status != svn_wc_status_ignored)&&(status != svn_wc_status_none))\r
+               {\r
+                       itemStatesFolder |= ITEMIS_FOLDERINSVN;\r
+               }\r
+               if (status == svn_wc_status_ignored)\r
+                       itemStatesFolder |= ITEMIS_IGNORED;\r
+               itemStatesFolder |= ITEMIS_FOLDER;\r
+               if (files_.size() == 0)\r
+                       itemStates |= ITEMIS_ONLYONE;\r
+               if (m_State != FileStateDropHandler)\r
+                       itemStates |= itemStatesFolder;\r
+       }\r
+       if (files_.size() == 2)\r
+               itemStates |= ITEMIS_TWO;\r
+       if ((files_.size() == 1)&&(g_ShellCache.IsContextPathAllowed(files_.front().c_str())))\r
+       {\r
+               itemStates |= ITEMIS_ONLYONE;\r
+               if (m_State != FileStateDropHandler)\r
+               {\r
+                       if (PathIsDirectory(files_.front().c_str()))\r
+                       {\r
+                               folder_ = files_.front();\r
+                               svn_wc_status_kind status = svn_wc_status_none;\r
+                               if (folder_.compare(statuspath)!=0)\r
+                               {\r
+                                       CTSVNPath askedpath;\r
+                                       askedpath.SetFromWin(folder_.c_str());\r
+                                       try\r
+                                       {\r
+                                               SVNStatus stat;\r
+                                               stat.GetStatus(CTSVNPath(folder_.c_str()), false, true, true);\r
+                                               if (stat.status)\r
+                                               {\r
+                                                       status = SVNStatus::GetMoreImportant(stat.status->text_status, stat.status->prop_status);\r
+                                                       if ((stat.status->entry)&&(stat.status->entry->lock_token))\r
+                                                               itemStates |= (stat.status->entry->lock_token[0] != 0) ? ITEMIS_LOCKED : 0;\r
+                                                       if ((stat.status->entry)&&(stat.status->entry->present_props))\r
+                                                       {\r
+                                                               if (strstr(stat.status->entry->present_props, "svn:needs-lock"))\r
+                                                                       itemStates |= ITEMIS_NEEDSLOCK;\r
+                                                       }\r
+                                                       if ((stat.status->entry)&&(stat.status->entry->uuid))\r
+                                                               uuidTarget = CUnicodeUtils::StdGetUnicode(stat.status->entry->uuid);\r
+                                               }\r
+                                       }\r
+                                       catch ( ... )\r
+                                       {\r
+                                               ATLTRACE2(_T("Exception in SVNStatus::GetAllStatus()\n"));\r
+                                       }\r
+                               }\r
+                               else\r
+                               {\r
+                                       status = fetchedstatus;\r
+                               }\r
+                               if ((status != svn_wc_status_unversioned)&&(status != svn_wc_status_ignored)&&(status != svn_wc_status_none))\r
+                                       itemStates |= ITEMIS_FOLDERINSVN;\r
+                               if (status == svn_wc_status_ignored)\r
+                                       itemStates |= ITEMIS_IGNORED;\r
+                               itemStates |= ITEMIS_FOLDER;\r
+                               if (status == svn_wc_status_added)\r
+                                       itemStates |= ITEMIS_ADDED;\r
+                               if (status == svn_wc_status_deleted)\r
+                                       itemStates |= ITEMIS_DELETED;\r
+                       }\r
+               }\r
+       }\r
+               \r
+       return NOERROR;\r
+}\r
+\r
+void CShellExt::InsertSVNMenu(BOOL istop, HMENU menu, UINT pos, UINT_PTR id, UINT stringid, UINT icon, UINT idCmdFirst, SVNCommands com, UINT uFlags)\r
+{\r
+       TCHAR menutextbuffer[255] = {0};\r
+       TCHAR verbsbuffer[255] = {0};\r
+       MAKESTRING(stringid);\r
+\r
+       if (istop)\r
+       {\r
+               //menu entry for the top context menu, so append an "SVN " before\r
+               //the menu text to indicate where the entry comes from\r
+               _tcscpy_s(menutextbuffer, 255, _T("SVN "));\r
+       }\r
+       _tcscat_s(menutextbuffer, 255, stringtablebuffer);\r
+       if ((fullver < 0x500)||(fullver == 0x500 && !uFlags))\r
+       {\r
+               InsertMenu(menu, pos, MF_BYPOSITION | MF_STRING , id, menutextbuffer);\r
+               if (fullver >= 0x500)\r
+               {\r
+                       // on win2k, the context menu does not work properly if we use\r
+                       // icon bitmaps. At least the menu text is empty in the context menu\r
+                       // for folder backgrounds (seems like a win2k bug).\r
+                       HBITMAP bmp = IconToBitmap(icon); \r
+                       SetMenuItemBitmaps(menu, pos, MF_BYPOSITION, bmp, bmp);\r
+               }\r
+       }\r
+       else\r
+       {\r
+               MENUITEMINFO menuiteminfo = {0};\r
+               menuiteminfo.cbSize = sizeof(menuiteminfo);\r
+               menuiteminfo.fMask = MIIM_FTYPE | MIIM_ID | MIIM_BITMAP | MIIM_STRING;\r
+               menuiteminfo.fType = MFT_STRING;\r
+               menuiteminfo.dwTypeData = menutextbuffer;\r
+               if (icon)\r
+                       menuiteminfo.hbmpItem = (fullver >= 0x600) ? IconToBitmapPARGB32(icon) : HBMMENU_CALLBACK;\r
+               menuiteminfo.wID = id;\r
+               InsertMenuItem(menu, pos, TRUE, &menuiteminfo);\r
+       }\r
+\r
+       if (istop)\r
+       {\r
+               //menu entry for the top context menu, so append an "SVN " before\r
+               //the menu text to indicate where the entry comes from\r
+               _tcscpy_s(menutextbuffer, 255, _T("SVN "));\r
+       }\r
+       LoadString(g_hResInst, stringid, verbsbuffer, sizeof(verbsbuffer));\r
+       _tcscat_s(menutextbuffer, 255, verbsbuffer);\r
+       stdstring verb = stdstring(menutextbuffer);\r
+       if (verb.find('&') != -1)\r
+       {\r
+               verb.erase(verb.find('&'),1);\r
+       }\r
+       myVerbsMap[verb] = id - idCmdFirst;\r
+       myVerbsMap[verb] = id;\r
+       myVerbsIDMap[id - idCmdFirst] = verb;\r
+       myVerbsIDMap[id] = verb;\r
+       // We store the relative and absolute diameter\r
+       // (drawitem callback uses absolute, others relative)\r
+       myIDMap[id - idCmdFirst] = com;\r
+       myIDMap[id] = com;\r
+       if (!istop)\r
+               mySubMenuMap[pos] = com;\r
+}\r
+\r
+HBITMAP CShellExt::IconToBitmap(UINT uIcon)\r
+{\r
+       std::map<UINT, HBITMAP>::iterator bitmap_it = bitmaps.lower_bound(uIcon);\r
+       if (bitmap_it != bitmaps.end() && bitmap_it->first == uIcon)\r
+               return bitmap_it->second;\r
+\r
+       HICON hIcon = (HICON)LoadImage(g_hResInst, MAKEINTRESOURCE(uIcon), IMAGE_ICON, 12, 12, LR_DEFAULTCOLOR);\r
+       if (!hIcon)\r
+               return NULL;\r
+\r
+       RECT rect;\r
+\r
+       rect.right = ::GetSystemMetrics(SM_CXMENUCHECK);\r
+       rect.bottom = ::GetSystemMetrics(SM_CYMENUCHECK);\r
+\r
+       rect.left = rect.top = 0;\r
+\r
+       HWND desktop = ::GetDesktopWindow();\r
+       if (desktop == NULL)\r
+       {\r
+               DestroyIcon(hIcon);\r
+               return NULL;\r
+       }\r
+\r
+       HDC screen_dev = ::GetDC(desktop);\r
+       if (screen_dev == NULL)\r
+       {\r
+               DestroyIcon(hIcon);\r
+               return NULL;\r
+       }\r
+\r
+       // Create a compatible DC\r
+       HDC dst_hdc = ::CreateCompatibleDC(screen_dev);\r
+       if (dst_hdc == NULL)\r
+       {\r
+               DestroyIcon(hIcon);\r
+               ::ReleaseDC(desktop, screen_dev); \r
+               return NULL;\r
+       }\r
+\r
+       // Create a new bitmap of icon size\r
+       HBITMAP bmp = ::CreateCompatibleBitmap(screen_dev, rect.right, rect.bottom);\r
+       if (bmp == NULL)\r
+       {\r
+               DestroyIcon(hIcon);\r
+               ::DeleteDC(dst_hdc);\r
+               ::ReleaseDC(desktop, screen_dev); \r
+               return NULL;\r
+       }\r
+\r
+       // Select it into the compatible DC\r
+       HBITMAP old_dst_bmp = (HBITMAP)::SelectObject(dst_hdc, bmp);\r
+       if (old_dst_bmp == NULL)\r
+       {\r
+               DestroyIcon(hIcon);\r
+               return NULL;\r
+       }\r
+\r
+       // Fill the background of the compatible DC with the white color\r
+       // that is taken by menu routines as transparent\r
+       ::SetBkColor(dst_hdc, RGB(255, 255, 255));\r
+       ::ExtTextOut(dst_hdc, 0, 0, ETO_OPAQUE, &rect, NULL, 0, NULL);\r
+\r
+       // Draw the icon into the compatible DC\r
+       ::DrawIconEx(dst_hdc, 0, 0, hIcon, rect.right, rect.bottom, 0, NULL, DI_NORMAL);\r
+\r
+       // Restore settings\r
+       ::SelectObject(dst_hdc, old_dst_bmp);\r
+       ::DeleteDC(dst_hdc);\r
+       ::ReleaseDC(desktop, screen_dev); \r
+       DestroyIcon(hIcon);\r
+       if (bmp)\r
+               bitmaps.insert(bitmap_it, std::make_pair(uIcon, bmp));\r
+       return bmp;\r
+}\r
+\r
+bool CShellExt::WriteClipboardPathsToTempFile(stdstring& tempfile)\r
+{\r
+       bool bRet = true;\r
+       tempfile = stdstring();\r
+       //write all selected files and paths to a temporary file\r
+       //for TortoiseProc.exe to read out again.\r
+       DWORD written = 0;\r
+       DWORD pathlength = GetTempPath(0, NULL);\r
+       TCHAR * path = new TCHAR[pathlength+1];\r
+       TCHAR * tempFile = new TCHAR[pathlength + 100];\r
+       GetTempPath (pathlength+1, path);\r
+       GetTempFileName (path, _T("svn"), 0, tempFile);\r
+       tempfile = stdstring(tempFile);\r
+\r
+       HANDLE file = ::CreateFile (tempFile,\r
+               GENERIC_WRITE, \r
+               FILE_SHARE_READ, \r
+               0, \r
+               CREATE_ALWAYS, \r
+               FILE_ATTRIBUTE_TEMPORARY,\r
+               0);\r
+\r
+       delete [] path;\r
+       delete [] tempFile;\r
+       if (file == INVALID_HANDLE_VALUE)\r
+               return false;\r
+\r
+       if (!IsClipboardFormatAvailable(CF_HDROP))\r
+               return false;\r
+       if (!OpenClipboard(NULL))\r
+               return false;\r
+\r
+       stdstring sClipboardText;\r
+       HGLOBAL hglb = GetClipboardData(CF_HDROP);\r
+       HDROP hDrop = (HDROP)GlobalLock(hglb);\r
+       if(hDrop != NULL)\r
+       {\r
+               TCHAR szFileName[MAX_PATH];\r
+               UINT cFiles = DragQueryFile(hDrop, 0xFFFFFFFF, NULL, 0); \r
+               for(UINT i = 0; i < cFiles; ++i)\r
+               {\r
+                       DragQueryFile(hDrop, i, szFileName, sizeof(szFileName));\r
+                       stdstring filename = szFileName;\r
+                       ::WriteFile (file, filename.c_str(), filename.size()*sizeof(TCHAR), &written, 0);\r
+                       ::WriteFile (file, _T("\n"), 2, &written, 0);\r
+               }\r
+               GlobalUnlock(hDrop);\r
+       }\r
+       else bRet = false;\r
+       GlobalUnlock(hglb);\r
+\r
+       CloseClipboard();\r
+       ::CloseHandle(file);\r
+\r
+       return bRet;\r
+}\r
+\r
+stdstring CShellExt::WriteFileListToTempFile()\r
+{\r
+       //write all selected files and paths to a temporary file\r
+       //for TortoiseProc.exe to read out again.\r
+       DWORD pathlength = GetTempPath(0, NULL);\r
+       TCHAR * path = new TCHAR[pathlength+1];\r
+       TCHAR * tempFile = new TCHAR[pathlength + 100];\r
+       GetTempPath (pathlength+1, path);\r
+       GetTempFileName (path, _T("svn"), 0, tempFile);\r
+       stdstring retFilePath = stdstring(tempFile);\r
+       \r
+       HANDLE file = ::CreateFile (tempFile,\r
+                                                               GENERIC_WRITE, \r
+                                                               FILE_SHARE_READ, \r
+                                                               0, \r
+                                                               CREATE_ALWAYS, \r
+                                                               FILE_ATTRIBUTE_TEMPORARY,\r
+                                                               0);\r
+\r
+       delete [] path;\r
+       delete [] tempFile;\r
+       if (file == INVALID_HANDLE_VALUE)\r
+               return stdstring();\r
+               \r
+       DWORD written = 0;\r
+       if (files_.empty())\r
+       {\r
+               ::WriteFile (file, folder_.c_str(), folder_.size()*sizeof(TCHAR), &written, 0);\r
+               ::WriteFile (file, _T("\n"), 2, &written, 0);\r
+       }\r
+\r
+       for (std::vector<stdstring>::iterator I = files_.begin(); I != files_.end(); ++I)\r
+       {\r
+               ::WriteFile (file, I->c_str(), I->size()*sizeof(TCHAR), &written, 0);\r
+               ::WriteFile (file, _T("\n"), 2, &written, 0);\r
+       }\r
+       ::CloseHandle(file);\r
+       return retFilePath;\r
+}\r
+\r
+STDMETHODIMP CShellExt::QueryDropContext(UINT uFlags, UINT idCmdFirst, HMENU hMenu, UINT &indexMenu)\r
+{\r
+       PreserveChdir preserveChdir;\r
+       LoadLangDll();\r
+\r
+       if ((uFlags & CMF_DEFAULTONLY)!=0)\r
+               return NOERROR;                                 //we don't change the default action\r
+\r
+       if ((files_.size() == 0)||(folder_.size() == 0))\r
+               return NOERROR;\r
+\r
+       if (((uFlags & 0x000f)!=CMF_NORMAL)&&(!(uFlags & CMF_EXPLORE))&&(!(uFlags & CMF_VERBSONLY)))\r
+               return NOERROR;\r
+\r
+       bool bSourceAndTargetFromSameRepository = (uuidSource.compare(uuidTarget) == 0) || uuidSource.empty() || uuidTarget.empty();\r
+\r
+       //the drop handler only has eight commands, but not all are visible at the same time:\r
+       //if the source file(s) are under version control then those files can be moved\r
+       //to the new location or they can be moved with a rename, \r
+       //if they are unversioned then they can be added to the working copy\r
+       //if they are versioned, they also can be exported to an unversioned location\r
+       UINT idCmd = idCmdFirst;\r
+\r
+       // SVN move here\r
+       // available if source is versioned but not added, target is versioned, source and target from same repository or target folder is added\r
+       if ((bSourceAndTargetFromSameRepository||(itemStatesFolder & ITEMIS_ADDED))&&(itemStatesFolder & ITEMIS_FOLDERINSVN)&&((itemStates & ITEMIS_INSVN)&&((~itemStates) & ITEMIS_ADDED)))\r
+               InsertSVNMenu(FALSE, hMenu, indexMenu++, idCmd++, IDS_DROPMOVEMENU, 0, idCmdFirst, ShellMenuDropMove, uFlags);\r
+\r
+       // SVN move and rename here\r
+       // available if source is a single, versioned but not added item, target is versioned, source and target from same repository or target folder is added\r
+       if ((bSourceAndTargetFromSameRepository||(itemStatesFolder & ITEMIS_ADDED))&&(itemStatesFolder & ITEMIS_FOLDERINSVN)&&(itemStates & ITEMIS_INSVN)&&(itemStates & ITEMIS_ONLYONE)&&((~itemStates) & ITEMIS_ADDED))\r
+               InsertSVNMenu(FALSE, hMenu, indexMenu++, idCmd++, IDS_DROPMOVERENAMEMENU, 0, idCmdFirst, ShellMenuDropMoveRename, uFlags);\r
+\r
+       // SVN copy here\r
+       // available if source is versioned but not added, target is versioned, source and target from same repository or target folder is added\r
+       if ((bSourceAndTargetFromSameRepository||(itemStatesFolder & ITEMIS_ADDED))&&(itemStatesFolder & ITEMIS_FOLDERINSVN)&&(itemStates & ITEMIS_INSVN)&&((~itemStates) & ITEMIS_ADDED))\r
+               InsertSVNMenu(FALSE, hMenu, indexMenu++, idCmd++, IDS_DROPCOPYMENU, 0, idCmdFirst, ShellMenuDropCopy, uFlags);\r
+\r
+       // SVN copy and rename here, source and target from same repository\r
+       // available if source is a single, versioned but not added item, target is versioned or target folder is added\r
+       if ((bSourceAndTargetFromSameRepository||(itemStatesFolder & ITEMIS_ADDED))&&(itemStatesFolder & ITEMIS_FOLDERINSVN)&&(itemStates & ITEMIS_INSVN)&&(itemStates & ITEMIS_ONLYONE)&&((~itemStates) & ITEMIS_ADDED))\r
+               InsertSVNMenu(FALSE, hMenu, indexMenu++, idCmd++, IDS_DROPCOPYRENAMEMENU, 0, idCmdFirst, ShellMenuDropCopyRename, uFlags);\r
+\r
+       // SVN add here\r
+       // available if target is versioned and source is either unversioned or from another repository\r
+       if ((itemStatesFolder & ITEMIS_FOLDERINSVN)&&(((~itemStates) & ITEMIS_INSVN)||!bSourceAndTargetFromSameRepository))\r
+               InsertSVNMenu(FALSE, hMenu, indexMenu++, idCmd++, IDS_DROPCOPYADDMENU, 0, idCmdFirst, ShellMenuDropCopyAdd, uFlags);\r
+\r
+       // SVN export here\r
+       // available if source is versioned and a folder\r
+       if ((itemStates & ITEMIS_INSVN)&&(itemStates & ITEMIS_FOLDER))\r
+               InsertSVNMenu(FALSE, hMenu, indexMenu++, idCmd++, IDS_DROPEXPORTMENU, 0, idCmdFirst, ShellMenuDropExport, uFlags);\r
+\r
+       // SVN export all here\r
+       // available if source is versioned and a folder\r
+       if ((itemStates & ITEMIS_INSVN)&&(itemStates & ITEMIS_FOLDER))\r
+               InsertSVNMenu(FALSE, hMenu, indexMenu++, idCmd++, IDS_DROPEXPORTEXTENDEDMENU, 0, idCmdFirst, ShellMenuDropExportExtended, uFlags);\r
+\r
+       // apply patch\r
+       // available if source is a patchfile\r
+       if (itemStates & ITEMIS_PATCHFILE)\r
+               InsertSVNMenu(FALSE, hMenu, indexMenu++, idCmd++, IDS_MENUAPPLYPATCH, 0, idCmdFirst, ShellMenuApplyPatch, uFlags);\r
+\r
+       // separator\r
+       if (idCmd != idCmdFirst)\r
+               InsertMenu(hMenu, indexMenu++, MF_SEPARATOR|MF_BYPOSITION, 0, NULL); \r
+\r
+       return ResultFromScode(MAKE_SCODE(SEVERITY_SUCCESS, 0, (USHORT)(idCmd - idCmdFirst)));\r
+}\r
+\r
+STDMETHODIMP CShellExt::QueryContextMenu(HMENU hMenu,\r
+                                         UINT indexMenu,\r
+                                         UINT idCmdFirst,\r
+                                         UINT /*idCmdLast*/,\r
+                                         UINT uFlags)\r
+{\r
+       ATLTRACE("Shell :: QueryContextMenu\n");\r
+       PreserveChdir preserveChdir;\r
+       \r
+       //first check if our drop handler is called\r
+       //and then (if true) provide the context menu for the\r
+       //drop handler\r
+       if (m_State == FileStateDropHandler)\r
+       {\r
+               return QueryDropContext(uFlags, idCmdFirst, hMenu, indexMenu);\r
+       }\r
+\r
+       if ((uFlags & CMF_DEFAULTONLY)!=0)\r
+               return NOERROR;                                 //we don't change the default action\r
+\r
+       if ((files_.size() == 0)&&(folder_.size() == 0))\r
+               return NOERROR;\r
+\r
+       if (((uFlags & 0x000f)!=CMF_NORMAL)&&(!(uFlags & CMF_EXPLORE))&&(!(uFlags & CMF_VERBSONLY)))\r
+               return NOERROR;\r
+\r
+       int csidlarray[] = \r
+       {\r
+               CSIDL_BITBUCKET,\r
+               CSIDL_CDBURN_AREA,\r
+               CSIDL_COMMON_FAVORITES,\r
+               CSIDL_COMMON_STARTMENU,\r
+               CSIDL_COMPUTERSNEARME,\r
+               CSIDL_CONNECTIONS,\r
+               CSIDL_CONTROLS,\r
+               CSIDL_COOKIES,\r
+               CSIDL_FAVORITES,\r
+               CSIDL_FONTS,\r
+               CSIDL_HISTORY,\r
+               CSIDL_INTERNET,\r
+               CSIDL_INTERNET_CACHE,\r
+               CSIDL_NETHOOD,\r
+               CSIDL_NETWORK,\r
+               CSIDL_PRINTERS,\r
+               CSIDL_PRINTHOOD,\r
+               CSIDL_RECENT,\r
+               CSIDL_SENDTO,\r
+               CSIDL_STARTMENU,\r
+               0\r
+       };\r
+       if (IsIllegalFolder(folder_, csidlarray))\r
+               return NOERROR;\r
+\r
+       if (folder_.empty())\r
+       {\r
+               // folder is empty, but maybe files are selected\r
+               if (files_.size() == 0)\r
+                       return NOERROR; // nothing selected - we don't have a menu to show\r
+               // check whether a selected entry is an UID - those are namespace extensions\r
+               // which we can't handle\r
+               for (std::vector<stdstring>::const_iterator it = files_.begin(); it != files_.end(); ++it)\r
+               {\r
+                       if (_tcsncmp(it->c_str(), _T("::{"), 3)==0)\r
+                               return NOERROR;\r
+               }\r
+       }\r
+\r
+       //check if our menu is requested for a subversion admin directory\r
+       if (g_SVNAdminDir.IsAdminDirPath(folder_.c_str()))\r
+               return NOERROR;\r
+\r
+       if (uFlags & CMF_EXTENDEDVERBS)\r
+               itemStates |= ITEMIS_EXTENDED;\r
+\r
+       const BOOL bShortcut = !!(uFlags & CMF_VERBSONLY);\r
+       if ( bShortcut && (files_.size()==1))\r
+       {\r
+               // Don't show the context menu for a link if the\r
+               // destination is not part of a working copy.\r
+               // It would only show the standard menu items\r
+               // which are already shown for the lnk-file.\r
+               CString path = files_.front().c_str();\r
+               if ( !g_SVNAdminDir.HasAdminDir(path) )\r
+               {\r
+                       return NOERROR;\r
+               }\r
+       }\r
+\r
+       //check if we already added our menu entry for a folder.\r
+       //we check that by iterating through all menu entries and check if \r
+       //the dwItemData member points to our global ID string. That string is set\r
+       //by our shell extension when the folder menu is inserted.\r
+       TCHAR menubuf[MAX_PATH];\r
+       int count = GetMenuItemCount(hMenu);\r
+       for (int i=0; i<count; ++i)\r
+       {\r
+               MENUITEMINFO miif;\r
+               SecureZeroMemory(&miif, sizeof(MENUITEMINFO));\r
+               miif.cbSize = sizeof(MENUITEMINFO);\r
+               miif.fMask = MIIM_DATA;\r
+               miif.dwTypeData = menubuf;\r
+               miif.cch = sizeof(menubuf)/sizeof(TCHAR);\r
+               GetMenuItemInfo(hMenu, i, TRUE, &miif);\r
+               if (miif.dwItemData == (ULONG_PTR)g_MenuIDString)\r
+                       return NOERROR;\r
+       }\r
+\r
+       LoadLangDll();\r
+       UINT idCmd = idCmdFirst;\r
+\r
+       //create the sub menu\r
+       HMENU subMenu = CreateMenu();\r
+       int indexSubMenu = 0;\r
+\r
+       unsigned __int64 topmenu = g_ShellCache.GetMenuLayout();\r
+       unsigned __int64 menumask = g_ShellCache.GetMenuMask();\r
+\r
+       int menuIndex = 0;\r
+       bool bAddSeparator = false;\r
+       bool bMenuEntryAdded = false;\r
+       // insert separator at start\r
+       InsertMenu(hMenu, indexMenu++, MF_SEPARATOR|MF_BYPOSITION, 0, NULL); idCmd++;\r
+       bool bShowIcons = !!DWORD(CRegStdWORD(_T("Software\\TortoiseSVN\\ShowContextMenuIcons"), TRUE));\r
+       if (fullver <= 0x0500)\r
+               bShowIcons = false;\r
+       while (menuInfo[menuIndex].command != ShellMenuLastEntry)\r
+       {\r
+               if (menuInfo[menuIndex].command == ShellSeparator)\r
+               {\r
+                       // we don't add a separator immediately. Because there might not be\r
+                       // another 'normal' menu entry after we insert a separator.\r
+                       // we simply set a flag here, indicating that before the next\r
+                       // 'normal' menu entry, a separator should be added.\r
+                       bAddSeparator = true;\r
+               }\r
+               else\r
+               {\r
+                       // check the conditions whether to show the menu entry or not\r
+                       bool bInsertMenu = false;\r
+\r
+                       if (menuInfo[menuIndex].firstyes && menuInfo[menuIndex].firstno)\r
+                       {\r
+                               if (((menuInfo[menuIndex].firstyes & itemStates) == menuInfo[menuIndex].firstyes)\r
+                                       &&\r
+                                       ((menuInfo[menuIndex].firstno & (~itemStates)) == menuInfo[menuIndex].firstno))\r
+                                       bInsertMenu = true;\r
+                       }\r
+                       else if ((menuInfo[menuIndex].firstyes)&&((menuInfo[menuIndex].firstyes & itemStates) == menuInfo[menuIndex].firstyes))\r
+                               bInsertMenu = true;\r
+                       else if ((menuInfo[menuIndex].firstno)&&((menuInfo[menuIndex].firstno & (~itemStates)) == menuInfo[menuIndex].firstno))\r
+                               bInsertMenu = true;\r
+\r
+                       if (menuInfo[menuIndex].secondyes && menuInfo[menuIndex].secondno)\r
+                       {\r
+                               if (((menuInfo[menuIndex].secondyes & itemStates) == menuInfo[menuIndex].secondyes)\r
+                                       &&\r
+                                       ((menuInfo[menuIndex].secondno & (~itemStates)) == menuInfo[menuIndex].secondno))\r
+                                       bInsertMenu = true;\r
+                       }\r
+                       else if ((menuInfo[menuIndex].secondyes)&&((menuInfo[menuIndex].secondyes & itemStates) == menuInfo[menuIndex].secondyes))\r
+                               bInsertMenu = true;\r
+                       else if ((menuInfo[menuIndex].secondno)&&((menuInfo[menuIndex].secondno & (~itemStates)) == menuInfo[menuIndex].secondno))\r
+                               bInsertMenu = true;\r
+\r
+                       if (menuInfo[menuIndex].thirdyes && menuInfo[menuIndex].thirdno)\r
+                       {\r
+                               if (((menuInfo[menuIndex].thirdyes & itemStates) == menuInfo[menuIndex].thirdyes)\r
+                                       &&\r
+                                       ((menuInfo[menuIndex].thirdno & (~itemStates)) == menuInfo[menuIndex].thirdno))\r
+                                       bInsertMenu = true;\r
+                       }\r
+                       else if ((menuInfo[menuIndex].thirdyes)&&((menuInfo[menuIndex].thirdyes & itemStates) == menuInfo[menuIndex].thirdyes))\r
+                               bInsertMenu = true;\r
+                       else if ((menuInfo[menuIndex].thirdno)&&((menuInfo[menuIndex].thirdno & (~itemStates)) == menuInfo[menuIndex].thirdno))\r
+                               bInsertMenu = true;\r
+\r
+                       if (menuInfo[menuIndex].fourthyes && menuInfo[menuIndex].fourthno)\r
+                       {\r
+                               if (((menuInfo[menuIndex].fourthyes & itemStates) == menuInfo[menuIndex].fourthyes)\r
+                                       &&\r
+                                       ((menuInfo[menuIndex].fourthno & (~itemStates)) == menuInfo[menuIndex].fourthno))\r
+                                       bInsertMenu = true;\r
+                       }\r
+                       else if ((menuInfo[menuIndex].fourthyes)&&((menuInfo[menuIndex].fourthyes & itemStates) == menuInfo[menuIndex].fourthyes))\r
+                               bInsertMenu = true;\r
+                       else if ((menuInfo[menuIndex].fourthno)&&((menuInfo[menuIndex].fourthno & (~itemStates)) == menuInfo[menuIndex].fourthno))\r
+                               bInsertMenu = true;\r
+\r
+                       if (menuInfo[menuIndex].menuID & (~menumask))\r
+                       {\r
+                               if (bInsertMenu)\r
+                               {\r
+                                       // insert a separator\r
+                                       if ((bMenuEntryAdded)&&(bAddSeparator))\r
+                                       {\r
+                                               bAddSeparator = false;\r
+                                               bMenuEntryAdded = false;\r
+                                               InsertMenu(subMenu, indexSubMenu++, MF_SEPARATOR|MF_BYPOSITION, 0, NULL); \r
+                                               idCmd++;\r
+                                       }\r
+                                       \r
+                                       // handle special cases (sub menus)\r
+                                       if ((menuInfo[menuIndex].command == ShellMenuIgnoreSub)||(menuInfo[menuIndex].command == ShellMenuUnIgnoreSub))\r
+                                       {\r
+                                               InsertIgnoreSubmenus(idCmd, idCmdFirst, hMenu, subMenu, indexMenu, indexSubMenu, topmenu, bShowIcons);\r
+                                               bMenuEntryAdded = true;\r
+                                       }\r
+                                       else\r
+                                       {\r
+                                               // the 'get lock' command is special\r
+                                               bool bIsTop = ((topmenu & menuInfo[menuIndex].menuID) != 0);\r
+                                               if (menuInfo[menuIndex].command == ShellMenuLock)\r
+                                               {\r
+                                                       if ((itemStates & ITEMIS_NEEDSLOCK) && g_ShellCache.IsGetLockTop())\r
+                                                               bIsTop = true;\r
+                                               }\r
+                                               // insert the menu entry\r
+                                               InsertSVNMenu(  bIsTop,\r
+                                                                               bIsTop ? hMenu : subMenu,\r
+                                                                               bIsTop ? indexMenu++ : indexSubMenu++,\r
+                                                                               idCmd++,\r
+                                                                               menuInfo[menuIndex].menuTextID,\r
+                                                                               bShowIcons ? menuInfo[menuIndex].iconID : 0,\r
+                                                                               idCmdFirst,\r
+                                                                               menuInfo[menuIndex].command,\r
+                                                                               uFlags);\r
+                                               if (!bIsTop)\r
+                                                       bMenuEntryAdded = true;\r
+                                       }\r
+                               }\r
+                       }\r
+               }\r
+               menuIndex++;\r
+       }\r
+\r
+       //add sub menu to main context menu\r
+       //don't use InsertMenu because this will lead to multiple menu entries in the explorer file menu.\r
+       //see http://support.microsoft.com/default.aspx?scid=kb;en-us;214477 for details of that.\r
+       MAKESTRING(IDS_MENUSUBMENU);\r
+       MENUITEMINFO menuiteminfo;\r
+       SecureZeroMemory(&menuiteminfo, sizeof(menuiteminfo));\r
+       menuiteminfo.cbSize = sizeof(menuiteminfo);\r
+       menuiteminfo.fType = MFT_STRING;\r
+       menuiteminfo.dwTypeData = stringtablebuffer;\r
+\r
+       UINT uIcon = bShowIcons ? IDI_APP : 0;\r
+       if (folder_.size())\r
+       {\r
+               uIcon = bShowIcons ? IDI_MENUFOLDER : 0;\r
+               myIDMap[idCmd - idCmdFirst] = ShellSubMenuFolder;\r
+               myIDMap[idCmd] = ShellSubMenuFolder;\r
+               menuiteminfo.dwItemData = (ULONG_PTR)g_MenuIDString;\r
+       }\r
+       else if (!bShortcut && (files_.size()==1))\r
+       {\r
+               uIcon = bShowIcons ? IDI_MENUFILE : 0;\r
+               myIDMap[idCmd - idCmdFirst] = ShellSubMenuFile;\r
+               myIDMap[idCmd] = ShellSubMenuFile;\r
+       }\r
+       else if (bShortcut && (files_.size()==1))\r
+       {\r
+               uIcon = bShowIcons ? IDI_MENULINK : 0;\r
+               myIDMap[idCmd - idCmdFirst] = ShellSubMenuLink;\r
+               myIDMap[idCmd] = ShellSubMenuLink;\r
+       }\r
+       else if (files_.size() > 1)\r
+       {\r
+               uIcon = bShowIcons ? IDI_MENUMULTIPLE : 0;\r
+               myIDMap[idCmd - idCmdFirst] = ShellSubMenuMultiple;\r
+               myIDMap[idCmd] = ShellSubMenuMultiple;\r
+       }\r
+       else\r
+       {\r
+               myIDMap[idCmd - idCmdFirst] = ShellSubMenu;\r
+               myIDMap[idCmd] = ShellSubMenu;\r
+       }\r
+       HBITMAP bmp = NULL;\r
+       if ((fullver < 0x500)||(fullver == 0x500 && !uFlags))\r
+       {\r
+               bmp = IconToBitmap(uIcon);\r
+               menuiteminfo.fMask = MIIM_STRING | MIIM_ID | MIIM_SUBMENU | MIIM_CHECKMARKS | MIIM_DATA;\r
+       }\r
+       else\r
+       {\r
+               menuiteminfo.fMask = MIIM_FTYPE | MIIM_ID | MIIM_SUBMENU | MIIM_DATA | MIIM_BITMAP | MIIM_STRING;\r
+               if (bShowIcons)\r
+                       menuiteminfo.hbmpItem = (fullver >= 0x600) ? IconToBitmapPARGB32(uIcon) : HBMMENU_CALLBACK;\r
+       }\r
+       menuiteminfo.hbmpChecked = bmp;\r
+       menuiteminfo.hbmpUnchecked = bmp;\r
+       menuiteminfo.hSubMenu = subMenu;\r
+       menuiteminfo.wID = idCmd++;\r
+       InsertMenuItem(hMenu, indexMenu++, TRUE, &menuiteminfo);\r
+\r
+       //separator after\r
+       InsertMenu(hMenu, indexMenu++, MF_SEPARATOR|MF_BYPOSITION, 0, NULL); idCmd++;\r
+\r
+       //return number of menu items added\r
+       return ResultFromScode(MAKE_SCODE(SEVERITY_SUCCESS, 0, (USHORT)(idCmd - idCmdFirst)));\r
+}\r
+\r
+\r
+// This is called when you invoke a command on the menu:\r
+STDMETHODIMP CShellExt::InvokeCommand(LPCMINVOKECOMMANDINFO lpcmi)\r
+{\r
+       PreserveChdir preserveChdir;\r
+       HRESULT hr = E_INVALIDARG;\r
+       if (lpcmi == NULL)\r
+               return hr;\r
+\r
+       std::string command;\r
+       std::string parent;\r
+       std::string file;\r
+\r
+       if ((files_.size() > 0)||(folder_.size() > 0))\r
+       {\r
+               UINT idCmd = LOWORD(lpcmi->lpVerb);\r
+\r
+               if (HIWORD(lpcmi->lpVerb))\r
+               {\r
+                       stdstring verb = stdstring(MultibyteToWide(lpcmi->lpVerb));\r
+                       std::map<stdstring, UINT_PTR>::const_iterator verb_it = myVerbsMap.lower_bound(verb);\r
+                       if (verb_it != myVerbsMap.end() && verb_it->first == verb)\r
+                               idCmd = verb_it->second;\r
+                       else\r
+                               return hr;\r
+               }\r
+\r
+               // See if we have a handler interface for this id\r
+               std::map<UINT_PTR, UINT_PTR>::const_iterator id_it = myIDMap.lower_bound(idCmd);\r
+               if (id_it != myIDMap.end() && id_it->first == idCmd)\r
+               {\r
+                       STARTUPINFO startup;\r
+                       PROCESS_INFORMATION process;\r
+                       memset(&startup, 0, sizeof(startup));\r
+                       startup.cb = sizeof(startup);\r
+                       memset(&process, 0, sizeof(process));\r
+                       CRegStdString tortoiseProcPath(_T("Software\\TortoiseSVN\\ProcPath"), _T("TortoiseProc.exe"), false, HKEY_LOCAL_MACHINE);\r
+                       CRegStdString tortoiseMergePath(_T("Software\\TortoiseSVN\\TMergePath"), _T("TortoiseMerge.exe"), false, HKEY_LOCAL_MACHINE);\r
+\r
+                       //TortoiseProc expects a command line of the form:\r
+                       //"/command:<commandname> /pathfile:<path> /startrev:<startrevision> /endrev:<endrevision> /deletepathfile\r
+                       // or\r
+                       //"/command:<commandname> /path:<path> /startrev:<startrevision> /endrev:<endrevision>\r
+                       //\r
+                       //* path is a path to a single file/directory for commands which only act on single items (log, checkout, ...)\r
+                       //* pathfile is a path to a temporary file which contains a list of file paths\r
+                       stdstring svnCmd = _T(" /command:");\r
+                       stdstring tempfile;\r
+                       switch (id_it->second)\r
+                       {\r
+                               //#region case\r
+                       case ShellMenuCheckout:\r
+                               svnCmd += _T("checkout /path:\"");\r
+                               svnCmd += folder_;\r
+                               svnCmd += _T("\"");\r
+                               break;\r
+                       case ShellMenuUpdate:\r
+                               tempfile = WriteFileListToTempFile();\r
+                               svnCmd += _T("update /pathfile:\"");\r
+                               svnCmd += tempfile;\r
+                               svnCmd += _T("\"");\r
+                               svnCmd += _T(" /deletepathfile");\r
+                               break;\r
+                       case ShellMenuUpdateExt:\r
+                               tempfile = WriteFileListToTempFile();\r
+                               svnCmd += _T("update /pathfile:\"");\r
+                               svnCmd += tempfile;\r
+                               svnCmd += _T("\"");\r
+                               svnCmd += _T(" /deletepathfile");\r
+                               svnCmd += _T(" /rev");\r
+                               break;\r
+                       case ShellMenuCommit:\r
+                               tempfile = WriteFileListToTempFile();\r
+                               svnCmd += _T("commit /pathfile:\"");\r
+                               svnCmd += tempfile;\r
+                               svnCmd += _T("\"");\r
+                               svnCmd += _T(" /deletepathfile");\r
+                               break;\r
+                       case ShellMenuAdd:\r
+                       case ShellMenuAddAsReplacement:\r
+                               tempfile = WriteFileListToTempFile();\r
+                               svnCmd += _T("add /pathfile:\"");\r
+                               svnCmd += tempfile;\r
+                               svnCmd += _T("\"");\r
+                               svnCmd += _T(" /deletepathfile");\r
+                               break;\r
+                       case ShellMenuIgnore:\r
+                               tempfile = WriteFileListToTempFile();\r
+                               svnCmd += _T("ignore /pathfile:\"");\r
+                               svnCmd += tempfile;\r
+                               svnCmd += _T("\"");\r
+                               svnCmd += _T(" /deletepathfile");\r
+                               break;\r
+                       case ShellMenuIgnoreCaseSensitive:\r
+                               tempfile = WriteFileListToTempFile();\r
+                               svnCmd += _T("ignore /pathfile:\"");\r
+                               svnCmd += tempfile;\r
+                               svnCmd += _T("\"");\r
+                               svnCmd += _T(" /deletepathfile");\r
+                               svnCmd += _T(" /onlymask");\r
+                               break;\r
+                       case ShellMenuUnIgnore:\r
+                               tempfile = WriteFileListToTempFile();\r
+                               svnCmd += _T("unignore /pathfile:\"");\r
+                               svnCmd += tempfile;\r
+                               svnCmd += _T("\"");\r
+                               svnCmd += _T(" /deletepathfile");\r
+                               break;\r
+                       case ShellMenuUnIgnoreCaseSensitive:\r
+                               tempfile = WriteFileListToTempFile();\r
+                               svnCmd += _T("unignore /pathfile:\"");\r
+                               svnCmd += tempfile;\r
+                               svnCmd += _T("\"");\r
+                               svnCmd += _T(" /deletepathfile");\r
+                               svnCmd += _T(" /onlymask");\r
+                               break;\r
+                       case ShellMenuRevert:\r
+                               tempfile = WriteFileListToTempFile();\r
+                               svnCmd += _T("revert /pathfile:\"");\r
+                               svnCmd += tempfile;\r
+                               svnCmd += _T("\"");\r
+                               svnCmd += _T(" /deletepathfile");\r
+                               break;\r
+                       case ShellMenuDelUnversioned:\r
+                               svnCmd += _T("delunversioned /path:\"");\r
+                               svnCmd += folder_;\r
+                               svnCmd += _T("\"");\r
+                               break;\r
+                       case ShellMenuCleanup:\r
+                               tempfile = WriteFileListToTempFile();\r
+                               svnCmd += _T("cleanup /pathfile:\"");\r
+                               svnCmd += tempfile;\r
+                               svnCmd += _T("\"");\r
+                               svnCmd += _T(" /deletepathfile");\r
+                               break;\r
+                       case ShellMenuResolve:\r
+                               tempfile = WriteFileListToTempFile();\r
+                               svnCmd += _T("resolve /pathfile:\"");\r
+                               svnCmd += tempfile;\r
+                               svnCmd += _T("\"");\r
+                               svnCmd += _T(" /deletepathfile");\r
+                               break;\r
+                       case ShellMenuSwitch:\r
+                               svnCmd += _T("switch /path:\"");\r
+                               if (files_.size() > 0)\r
+                                       svnCmd += files_.front();\r
+                               else\r
+                                       svnCmd += folder_;\r
+                               svnCmd += _T("\"");\r
+                               break;\r
+                       case ShellMenuImport:\r
+                               svnCmd += _T("import /path:\"");\r
+                               svnCmd += folder_;\r
+                               svnCmd += _T("\"");\r
+                               break;\r
+                       case ShellMenuExport:\r
+                               svnCmd += _T("export /path:\"");\r
+                               svnCmd += folder_;\r
+                               svnCmd += _T("\"");\r
+                               break;\r
+                       case ShellMenuAbout:\r
+                               svnCmd += _T("about");\r
+                               break;\r
+                       case ShellMenuCreateRepos:\r
+                               svnCmd += _T("repocreate /path:\"");\r
+                               svnCmd += folder_;\r
+                               svnCmd += _T("\"");\r
+                               break;\r
+                       case ShellMenuMerge:\r
+                               svnCmd += _T("merge /path:\"");\r
+                               if (files_.size() > 0)\r
+                                       svnCmd += files_.front();\r
+                               else\r
+                                       svnCmd += folder_;\r
+                               svnCmd += _T("\"");\r
+                               break;\r
+                       case ShellMenuMergeAll:\r
+                               svnCmd += _T("mergeall /path:\"");\r
+                               if (files_.size() > 0)\r
+                                       svnCmd += files_.front();\r
+                               else\r
+                                       svnCmd += folder_;\r
+                               svnCmd += _T("\"");\r
+                               break;\r
+                       case ShellMenuCopy:\r
+                               svnCmd += _T("copy /path:\"");\r
+                               if (files_.size() > 0)\r
+                                       svnCmd += files_.front();\r
+                               else\r
+                                       svnCmd += folder_;\r
+                               svnCmd += _T("\"");\r
+                               break;\r
+                       case ShellMenuSettings:\r
+                               svnCmd += _T("settings");\r
+                               break;\r
+                       case ShellMenuHelp:\r
+                               svnCmd += _T("help");\r
+                               break;\r
+                       case ShellMenuRename:\r
+                               svnCmd += _T("rename /path:\"");\r
+                               if (files_.size() > 0)\r
+                                       svnCmd += files_.front();\r
+                               else\r
+                                       svnCmd += folder_;\r
+                               svnCmd += _T("\"");\r
+                               break;\r
+                       case ShellMenuRemove:\r
+                               tempfile = WriteFileListToTempFile();\r
+                               svnCmd += _T("remove /pathfile:\"");\r
+                               svnCmd += tempfile;\r
+                               svnCmd += _T("\"");\r
+                               svnCmd += _T(" /deletepathfile");\r
+                               break;\r
+                       case ShellMenuRemoveKeep:\r
+                               tempfile = WriteFileListToTempFile();\r
+                               svnCmd += _T("remove /pathfile:\"");\r
+                               svnCmd += tempfile;\r
+                               svnCmd += _T("\"");\r
+                               svnCmd += _T(" /deletepathfile");\r
+                               svnCmd += _T(" /keep");\r
+                               break;\r
+                       case ShellMenuDiff:\r
+                               svnCmd += _T("diff /path:\"");\r
+                               if (files_.size() == 1)\r
+                                       svnCmd += files_.front();\r
+                               else if (files_.size() == 2)\r
+                               {\r
+                                       std::vector<stdstring>::iterator I = files_.begin();\r
+                                       svnCmd += *I;\r
+                                       I++;\r
+                                       svnCmd += _T("\" /path2:\"");\r
+                                       svnCmd += *I;\r
+                               }\r
+                               else\r
+                                       svnCmd += folder_;\r
+                               svnCmd += _T("\"");\r
+                               if (GetAsyncKeyState(VK_SHIFT) & 0x8000)\r
+                                       svnCmd += _T(" /alternative");\r
+                               break;\r
+                       case ShellMenuPrevDiff:\r
+                               svnCmd += _T("prevdiff /path:\"");\r
+                               if (files_.size() == 1)\r
+                                       svnCmd += files_.front();\r
+                               else\r
+                                       svnCmd += folder_;\r
+                               svnCmd += _T("\"");\r
+                               if (GetAsyncKeyState(VK_SHIFT) & 0x8000)\r
+                                       svnCmd += _T(" /alternative");\r
+                               break;\r
+                       case ShellMenuUrlDiff:\r
+                               svnCmd += _T("urldiff /path:\"");\r
+                               if (files_.size() == 1)\r
+                                       svnCmd += files_.front();\r
+                               else\r
+                                       svnCmd += folder_;\r
+                               svnCmd += _T("\"");\r
+                               break;\r
+                       case ShellMenuDropCopyAdd:\r
+                               tempfile = WriteFileListToTempFile();\r
+                               svnCmd += _T("dropcopyadd /pathfile:\"");\r
+                               svnCmd += tempfile;\r
+                               svnCmd += _T("\"");\r
+                               svnCmd += _T(" /deletepathfile");\r
+                               svnCmd += _T(" /droptarget:\"");\r
+                               svnCmd += folder_;\r
+                               svnCmd += _T("\"";)\r
+                                       break;\r
+                       case ShellMenuDropCopy:\r
+                               tempfile = WriteFileListToTempFile();\r
+                               svnCmd += _T("dropcopy /pathfile:\"");\r
+                               svnCmd += tempfile;\r
+                               svnCmd += _T("\"");\r
+                               svnCmd += _T(" /deletepathfile");\r
+                               svnCmd += _T(" /droptarget:\"");\r
+                               svnCmd += folder_;\r
+                               svnCmd += _T("\"";)\r
+                                       break;\r
+                       case ShellMenuDropCopyRename:\r
+                               tempfile = WriteFileListToTempFile();\r
+                               svnCmd += _T("dropcopy /pathfile:\"");\r
+                               svnCmd += tempfile;\r
+                               svnCmd += _T("\"");\r
+                               svnCmd += _T(" /deletepathfile");\r
+                               svnCmd += _T(" /droptarget:\"");\r
+                               svnCmd += folder_;\r
+                               svnCmd += _T("\" /rename";)\r
+                                       break;\r
+                       case ShellMenuDropMove:\r
+                               tempfile = WriteFileListToTempFile();\r
+                               svnCmd += _T("dropmove /pathfile:\"");\r
+                               svnCmd += tempfile;\r
+                               svnCmd += _T("\"");\r
+                               svnCmd += _T(" /deletepathfile");\r
+                               svnCmd += _T(" /droptarget:\"");\r
+                               svnCmd += folder_;\r
+                               svnCmd += _T("\"");\r
+                               break;\r
+                       case ShellMenuDropMoveRename:\r
+                               tempfile = WriteFileListToTempFile();\r
+                               svnCmd += _T("dropmove /pathfile:\"");\r
+                               svnCmd += tempfile;\r
+                               svnCmd += _T("\"");\r
+                               svnCmd += _T(" /deletepathfile");\r
+                               svnCmd += _T(" /droptarget:\"");\r
+                               svnCmd += folder_;\r
+                               svnCmd += _T("\" /rename";)\r
+                               break;\r
+                       case ShellMenuDropExport:\r
+                               tempfile = WriteFileListToTempFile();\r
+                               svnCmd += _T("dropexport /pathfile:\"");\r
+                               svnCmd += tempfile;\r
+                               svnCmd += _T("\"");\r
+                               svnCmd += _T(" /deletepathfile");\r
+                               svnCmd += _T(" /droptarget:\"");\r
+                               svnCmd += folder_;\r
+                               svnCmd += _T("\"");\r
+                               break;\r
+                       case ShellMenuDropExportExtended:\r
+                               tempfile = WriteFileListToTempFile();\r
+                               svnCmd += _T("dropexport /pathfile:\"");\r
+                               svnCmd += tempfile;\r
+                               svnCmd += _T("\"");\r
+                               svnCmd += _T(" /deletepathfile");\r
+                               svnCmd += _T(" /droptarget:\"");\r
+                               svnCmd += folder_;\r
+                               svnCmd += _T("\"");\r
+                               svnCmd += _T(" /extended");\r
+                               break;\r
+                       case ShellMenuLog:\r
+                               svnCmd += _T("log /path:\"");\r
+                               if (files_.size() > 0)\r
+                                       svnCmd += files_.front();\r
+                               else\r
+                                       svnCmd += folder_;\r
+                               svnCmd += _T("\"");\r
+                               break;\r
+                       case ShellMenuConflictEditor:\r
+                               svnCmd += _T("conflicteditor /path:\"");\r
+                               if (files_.size() > 0)\r
+                                       svnCmd += files_.front();\r
+                               else\r
+                                       svnCmd += folder_;\r
+                               svnCmd += _T("\"");\r
+                               break;\r
+                       case ShellMenuRelocate:\r
+                               svnCmd += _T("relocate /path:\"");\r
+                               if (files_.size() > 0)\r
+                                       svnCmd += files_.front();\r
+                               else\r
+                                       svnCmd += folder_;\r
+                               svnCmd += _T("\"");\r
+                               break;\r
+                       case ShellMenuShowChanged:\r
+                               if (files_.size() > 1)\r
+                {\r
+                                   tempfile = WriteFileListToTempFile();\r
+                                   svnCmd += _T("repostatus /pathfile:\"");\r
+                                   svnCmd += tempfile;\r
+                               svnCmd += _T("\"");\r
+                               svnCmd += _T(" /deletepathfile");\r
+                }\r
+                else\r
+                {\r
+                    svnCmd += _T("repostatus /path:\"");\r
+                                   if (files_.size() > 0)\r
+                                           svnCmd += files_.front();\r
+                                   else\r
+                                           svnCmd += folder_;\r
+                               svnCmd += _T("\"");\r
+                }\r
+                               break;\r
+                       case ShellMenuRepoBrowse:\r
+                               svnCmd += _T("repobrowser /path:\"");\r
+                               if (files_.size() > 0)\r
+                                       svnCmd += files_.front();\r
+                               else\r
+                                       svnCmd += folder_;\r
+                               svnCmd += _T("\"");\r
+                               break;\r
+                       case ShellMenuBlame:\r
+                               svnCmd += _T("blame /path:\"");\r
+                               if (files_.size() > 0)\r
+                                       svnCmd += files_.front();\r
+                               else\r
+                                       svnCmd += folder_;\r
+                               svnCmd += _T("\"");\r
+                               break;\r
+                       case ShellMenuCreatePatch:\r
+                               tempfile = WriteFileListToTempFile();\r
+                               svnCmd += _T("createpatch /pathfile:\"");\r
+                               svnCmd += tempfile;\r
+                               svnCmd += _T("\"");\r
+                               svnCmd += _T(" /deletepathfile");\r
+                               break;\r
+                       case ShellMenuApplyPatch:\r
+                               if ((itemStates & ITEMIS_PATCHINCLIPBOARD) && ((~itemStates) & ITEMIS_PATCHFILE))\r
+                               {\r
+                                       // if there's a patch file in the clipboard, we save it\r
+                                       // to a temporary file and tell TortoiseMerge to use that one\r
+                                       UINT cFormat = RegisterClipboardFormat(_T("TSVN_UNIFIEDDIFF"));\r
+                                       if ((cFormat)&&(OpenClipboard(NULL)))\r
+                                       { \r
+                                               HGLOBAL hglb = GetClipboardData(cFormat); \r
+                                               LPCSTR lpstr = (LPCSTR)GlobalLock(hglb); \r
+\r
+                                               DWORD len = GetTempPath(0, NULL);\r
+                                               TCHAR * path = new TCHAR[len+1];\r
+                                               TCHAR * tempF = new TCHAR[len+100];\r
+                                               GetTempPath (len+1, path);\r
+                                               GetTempFileName (path, TEXT("svn"), 0, tempF);\r
+                                               std::wstring sTempFile = std::wstring(tempF);\r
+                                               delete [] path;\r
+                                               delete [] tempF;\r
+\r
+                                               FILE * outFile;\r
+                                               size_t patchlen = strlen(lpstr);\r
+                                               _tfopen_s(&outFile, sTempFile.c_str(), _T("wb"));\r
+                                               if(outFile)\r
+                                               {\r
+                                                       size_t size = fwrite(lpstr, sizeof(char), patchlen, outFile);\r
+                                                       if (size == patchlen)\r
+                                                       {\r
+                                                               itemStates |= ITEMIS_PATCHFILE;\r
+                                                               files_.clear();\r
+                                                               files_.push_back(sTempFile);\r
+                                                       }\r
+                                                       fclose(outFile);\r
+                                               }\r
+                                               GlobalUnlock(hglb); \r
+                                               CloseClipboard(); \r
+                                       } \r
+                               }\r
+                               if (itemStates & ITEMIS_PATCHFILE)\r
+                               {\r
+                                       svnCmd = _T(" /diff:\"");\r
+                                       if (files_.size() > 0)\r
+                                       {\r
+                                               svnCmd += files_.front();\r
+                                               if (itemStatesFolder & ITEMIS_FOLDERINSVN)\r
+                                               {\r
+                                                       svnCmd += _T("\" /patchpath:\"");\r
+                                                       svnCmd += folder_;\r
+                                               }\r
+                                       }\r
+                                       else\r
+                                               svnCmd += folder_;\r
+                                       if (itemStates & ITEMIS_INVERSIONEDFOLDER)\r
+                                               svnCmd += _T("\" /wc");\r
+                                       else\r
+                                               svnCmd += _T("\"");\r
+                               }\r
+                               else\r
+                               {\r
+                                       svnCmd = _T(" /patchpath:\"");\r
+                                       if (files_.size() > 0)\r
+                                               svnCmd += files_.front();\r
+                                       else\r
+                                               svnCmd += folder_;\r
+                                       svnCmd += _T("\"");\r
+                               }\r
+                               myIDMap.clear();\r
+                               myVerbsIDMap.clear();\r
+                               myVerbsMap.clear();\r
+                               if (CreateProcess(((stdstring)tortoiseMergePath).c_str(), const_cast<TCHAR*>(svnCmd.c_str()), NULL, NULL, FALSE, 0, 0, 0, &startup, &process)==0)\r
+                               {\r
+                                       LPVOID lpMsgBuf;\r
+                                       FormatMessage(FORMAT_MESSAGE_ALLOCATE_BUFFER | \r
+                                               FORMAT_MESSAGE_FROM_SYSTEM | \r
+                                               FORMAT_MESSAGE_IGNORE_INSERTS,\r
+                                               NULL,\r
+                                               GetLastError(),\r
+                                               MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), // Default language\r
+                                               (LPTSTR) &lpMsgBuf,\r
+                                               0,\r
+                                               NULL \r
+                                               );\r
+                                       MessageBox( NULL, (LPCTSTR)lpMsgBuf, _T("TortoiseMerge launch failed"), MB_OK | MB_ICONINFORMATION );\r
+                                       LocalFree( lpMsgBuf );\r
+                               }\r
+                               CloseHandle(process.hThread);\r
+                               CloseHandle(process.hProcess);\r
+                               return NOERROR;\r
+                               break;\r
+                       case ShellMenuRevisionGraph:\r
+                               svnCmd += _T("revisiongraph /path:\"");\r
+                               if (files_.size() > 0)\r
+                                       svnCmd += files_.front();\r
+                               else\r
+                                       svnCmd += folder_;\r
+                               svnCmd += _T("\"");\r
+                               break;\r
+                       case ShellMenuLock:\r
+                               tempfile = WriteFileListToTempFile();\r
+                               svnCmd += _T("lock /pathfile:\"");\r
+                               svnCmd += tempfile;\r
+                               svnCmd += _T("\"");\r
+                               svnCmd += _T(" /deletepathfile");\r
+                               break;\r
+                       case ShellMenuUnlock:\r
+                               tempfile = WriteFileListToTempFile();\r
+                               svnCmd += _T("unlock /pathfile:\"");\r
+                               svnCmd += tempfile;\r
+                               svnCmd += _T("\"");\r
+                               svnCmd += _T(" /deletepathfile");\r
+                               break;\r
+                       case ShellMenuUnlockForce:\r
+                               tempfile = WriteFileListToTempFile();\r
+                               svnCmd += _T("unlock /pathfile:\"");\r
+                               svnCmd += tempfile;\r
+                               svnCmd += _T("\"");\r
+                               svnCmd += _T(" /deletepathfile");\r
+                               svnCmd += _T(" /force");\r
+                               break;\r
+                       case ShellMenuProperties:\r
+                               tempfile = WriteFileListToTempFile();\r
+                               svnCmd += _T("properties /pathfile:\"");\r
+                               svnCmd += tempfile;\r
+                               svnCmd += _T("\"");\r
+                               svnCmd += _T(" /deletepathfile");\r
+                               break;\r
+                       case ShellMenuClipPaste:\r
+                               if (WriteClipboardPathsToTempFile(tempfile))\r
+                               {\r
+                                       bool bCopy = true;\r
+                                       UINT cPrefDropFormat = RegisterClipboardFormat(_T("Preferred DropEffect"));\r
+                                       if (cPrefDropFormat)\r
+                                       {\r
+                                               if (OpenClipboard(lpcmi->hwnd))\r
+                                               {\r
+                                                       HGLOBAL hglb = GetClipboardData(cPrefDropFormat);\r
+                                                       if (hglb)\r
+                                                       {\r
+                                                               DWORD* effect = (DWORD*) GlobalLock(hglb);\r
+                                                               if (*effect == DROPEFFECT_MOVE)\r
+                                                                       bCopy = false;\r
+                                                               GlobalUnlock(hglb);\r
+                                                       }\r
+                                                       CloseClipboard();\r
+                                               }\r
+                                       }\r
+\r
+                                       if (bCopy)\r
+                                               svnCmd += _T("pastecopy /pathfile:\"");\r
+                                       else\r
+                                               svnCmd += _T("pastemove /pathfile:\"");\r
+                                       svnCmd += tempfile;\r
+                                       svnCmd += _T("\"");\r
+                                       svnCmd += _T(" /deletepathfile");\r
+                                       svnCmd += _T(" /droptarget:\"");\r
+                                       svnCmd += folder_;\r
+                                       svnCmd += _T("\"");\r
+                               }\r
+                               else return NOERROR;\r
+                               break;\r
+                       default:\r
+                               break;\r
+                               //#endregion\r
+                       } // switch (id_it->second) \r
+                       svnCmd += _T(" /hwnd:");\r
+                       TCHAR buf[30];\r
+                       _stprintf_s(buf, 30, _T("%d"), lpcmi->hwnd);\r
+                       svnCmd += buf;\r
+                       myIDMap.clear();\r
+                       myVerbsIDMap.clear();\r
+                       myVerbsMap.clear();\r
+                       if (CreateProcess(((stdstring)tortoiseProcPath).c_str(), const_cast<TCHAR*>(svnCmd.c_str()), NULL, NULL, FALSE, 0, 0, 0, &startup, &process)==0)\r
+                       {\r
+                               LPVOID lpMsgBuf;\r
+                               FormatMessage(FORMAT_MESSAGE_ALLOCATE_BUFFER | \r
+                                       FORMAT_MESSAGE_FROM_SYSTEM | \r
+                                       FORMAT_MESSAGE_IGNORE_INSERTS,\r
+                                       NULL,\r
+                                       GetLastError(),\r
+                                       MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), // Default language\r
+                                       (LPTSTR) &lpMsgBuf,\r
+                                       0,\r
+                                       NULL \r
+                                       );\r
+                               MessageBox( NULL, (LPCTSTR)lpMsgBuf, _T("TortoiseProc Launch failed"), MB_OK | MB_ICONINFORMATION );\r
+                               LocalFree( lpMsgBuf );\r
+                       }\r
+                       CloseHandle(process.hThread);\r
+                       CloseHandle(process.hProcess);\r
+                       hr = NOERROR;\r
+               } // if (id_it != myIDMap.end() && id_it->first == idCmd) \r
+       } // if ((files_.size() > 0)||(folder_.size() > 0)) \r
+       return hr;\r
+\r
+}\r
+\r
+// This is for the status bar and things like that:\r
+STDMETHODIMP CShellExt::GetCommandString(UINT_PTR idCmd,\r
+                                         UINT uFlags,\r
+                                         UINT FAR * /*reserved*/,\r
+                                         LPSTR pszName,\r
+                                         UINT cchMax)\r
+{\r
+       PreserveChdir preserveChdir;\r
+       //do we know the id?\r
+       std::map<UINT_PTR, UINT_PTR>::const_iterator id_it = myIDMap.lower_bound(idCmd);\r
+       if (id_it == myIDMap.end() || id_it->first != idCmd)\r
+       {\r
+               return E_INVALIDARG;            //no, we don't\r
+       }\r
+\r
+       LoadLangDll();\r
+       HRESULT hr = E_INVALIDARG;\r
+\r
+       MAKESTRING(IDS_MENUDESCDEFAULT);\r
+       int menuIndex = 0;\r
+       while (menuInfo[menuIndex].command != ShellMenuLastEntry)\r
+       {\r
+               if (menuInfo[menuIndex].command == (SVNCommands)id_it->second)\r
+               {\r
+                       MAKESTRING(menuInfo[menuIndex].menuDescID);\r
+                       break;\r
+               }\r
+               menuIndex++;\r
+       }\r
+\r
+       const TCHAR * desc = stringtablebuffer;\r
+       switch(uFlags)\r
+       {\r
+       case GCS_HELPTEXTA:\r
+               {\r
+                       std::string help = WideToMultibyte(desc);\r
+                       lstrcpynA(pszName, help.c_str(), cchMax);\r
+                       hr = S_OK;\r
+                       break; \r
+               }\r
+       case GCS_HELPTEXTW: \r
+               {\r
+                       wide_string help = desc;\r
+                       lstrcpynW((LPWSTR)pszName, help.c_str(), cchMax); \r
+                       hr = S_OK;\r
+                       break; \r
+               }\r
+       case GCS_VERBA:\r
+               {\r
+                       std::map<UINT_PTR, stdstring>::const_iterator verb_id_it = myVerbsIDMap.lower_bound(idCmd);\r
+                       if (verb_id_it != myVerbsIDMap.end() && verb_id_it->first == idCmd)\r
+                       {\r
+                               std::string help = WideToMultibyte(verb_id_it->second);\r
+                               lstrcpynA(pszName, help.c_str(), cchMax);\r
+                               hr = S_OK;\r
+                       }\r
+               }\r
+               break;\r
+       case GCS_VERBW:\r
+               {\r
+                       std::map<UINT_PTR, stdstring>::const_iterator verb_id_it = myVerbsIDMap.lower_bound(idCmd);\r
+                       if (verb_id_it != myVerbsIDMap.end() && verb_id_it->first == idCmd)\r
+                       {\r
+                               wide_string help = verb_id_it->second;\r
+                               ATLTRACE("verb : %ws\n", help.c_str());\r
+                               lstrcpynW((LPWSTR)pszName, help.c_str(), cchMax); \r
+                               hr = S_OK;\r
+                       }\r
+               }\r
+               break;\r
+       }\r
+       return hr;\r
+}\r
+\r
+STDMETHODIMP CShellExt::HandleMenuMsg(UINT uMsg, WPARAM wParam, LPARAM lParam)\r
+{\r
+       LRESULT res;\r
+       return HandleMenuMsg2(uMsg, wParam, lParam, &res);\r
+}\r
+\r
+STDMETHODIMP CShellExt::HandleMenuMsg2(UINT uMsg, WPARAM wParam, LPARAM lParam, LRESULT *pResult)\r
+{\r
+       PreserveChdir preserveChdir;\r
+\r
+       LRESULT res;\r
+       if (pResult == NULL)\r
+               pResult = &res;\r
+       *pResult = FALSE;\r
+\r
+       LoadLangDll();\r
+       switch (uMsg)\r
+       {\r
+       case WM_MEASUREITEM:\r
+               {\r
+                       MEASUREITEMSTRUCT* lpmis = (MEASUREITEMSTRUCT*)lParam;\r
+                       if (lpmis==NULL)\r
+                               break;\r
+                       lpmis->itemWidth += 2;\r
+                       if (lpmis->itemHeight < 16)\r
+                               lpmis->itemHeight = 16;\r
+                       *pResult = TRUE;\r
+               }\r
+               break;\r
+       case WM_DRAWITEM:\r
+               {\r
+                       LPCTSTR resource;\r
+                       DRAWITEMSTRUCT* lpdis = (DRAWITEMSTRUCT*)lParam;\r
+                       if ((lpdis==NULL)||(lpdis->CtlType != ODT_MENU))\r
+                               return S_OK;            //not for a menu\r
+                       resource = GetMenuTextFromResource(myIDMap[lpdis->itemID]);\r
+                       if (resource == NULL)\r
+                               return S_OK;\r
+                       HICON hIcon = (HICON)LoadImage(g_hResInst, resource, IMAGE_ICON, 16, 16, LR_DEFAULTCOLOR);\r
+                       if (hIcon == NULL)\r
+                               return S_OK;\r
+                       DrawIconEx(lpdis->hDC,\r
+                               lpdis->rcItem.left - 16,\r
+                               lpdis->rcItem.top + (lpdis->rcItem.bottom - lpdis->rcItem.top - 16) / 2,\r
+                               hIcon, 16, 16,\r
+                               0, NULL, DI_NORMAL);\r
+                       DestroyIcon(hIcon);\r
+                       *pResult = TRUE;\r
+               }\r
+               break;\r
+       case WM_MENUCHAR:\r
+               {\r
+                       LPCTSTR resource;\r
+                       TCHAR *szItem;\r
+                       if (HIWORD(wParam) != MF_POPUP)\r
+                               return NOERROR;\r
+                       int nChar = LOWORD(wParam);\r
+                       if (_istascii((wint_t)nChar) && _istupper((wint_t)nChar))\r
+                               nChar = tolower(nChar);\r
+                       // we have the char the user pressed, now search that char in all our\r
+                       // menu items\r
+                       std::vector<int> accmenus;\r
+                       for (std::map<UINT_PTR, UINT_PTR>::iterator It = mySubMenuMap.begin(); It != mySubMenuMap.end(); ++It)\r
+                       {\r
+                               resource = GetMenuTextFromResource(mySubMenuMap[It->first]);\r
+                               if (resource == NULL)\r
+                                       continue;\r
+                               szItem = stringtablebuffer;\r
+                               TCHAR * amp = _tcschr(szItem, '&');\r
+                               if (amp == NULL)\r
+                                       continue;\r
+                               amp++;\r
+                               int ampChar = LOWORD(*amp);\r
+                               if (_istascii((wint_t)ampChar) && _istupper((wint_t)ampChar))\r
+                                       ampChar = tolower(ampChar);\r
+                               if (ampChar == nChar)\r
+                               {\r
+                                       // yep, we found a menu which has the pressed key\r
+                                       // as an accelerator. Add that menu to the list to\r
+                                       // process later.\r
+                                       accmenus.push_back(It->first);\r
+                               }\r
+                       }\r
+                       if (accmenus.size() == 0)\r
+                       {\r
+                               // no menu with that accelerator key.\r
+                               *pResult = MAKELONG(0, MNC_IGNORE);\r
+                               return NOERROR;\r
+                       }\r
+                       if (accmenus.size() == 1)\r
+                       {\r
+                               // Only one menu with that accelerator key. We're lucky!\r
+                               // So just execute that menu entry.\r
+                               *pResult = MAKELONG(accmenus[0], MNC_EXECUTE);\r
+                               return NOERROR;\r
+                       }\r
+                       if (accmenus.size() > 1)\r
+                       {\r
+                               // we have more than one menu item with this accelerator key!\r
+                               MENUITEMINFO mif;\r
+                               mif.cbSize = sizeof(MENUITEMINFO);\r
+                               mif.fMask = MIIM_STATE;\r
+                               for (std::vector<int>::iterator it = accmenus.begin(); it != accmenus.end(); ++it)\r
+                               {\r
+                                       GetMenuItemInfo((HMENU)lParam, *it, TRUE, &mif);\r
+                                       if (mif.fState == MFS_HILITE)\r
+                                       {\r
+                                               // this is the selected item, so select the next one\r
+                                               ++it;\r
+                                               if (it == accmenus.end())\r
+                                                       *pResult = MAKELONG(accmenus[0], MNC_SELECT);\r
+                                               else\r
+                                                       *pResult = MAKELONG(*it, MNC_SELECT);\r
+                                               return NOERROR;\r
+                                       }\r
+                               }\r
+                               *pResult = MAKELONG(accmenus[0], MNC_SELECT);\r
+                       }\r
+               }\r
+               break;\r
+       default:\r
+               return NOERROR;\r
+       }\r
+\r
+       return NOERROR;\r
+}\r
+\r
+LPCTSTR CShellExt::GetMenuTextFromResource(int id)\r
+{\r
+       TCHAR textbuf[255];\r
+       LPCTSTR resource = NULL;\r
+       unsigned __int64 layout = g_ShellCache.GetMenuLayout();\r
+       space = 6;\r
+\r
+       int menuIndex = 0;\r
+       while (menuInfo[menuIndex].command != ShellMenuLastEntry)\r
+       {\r
+               if (menuInfo[menuIndex].command == id)\r
+               {\r
+                       MAKESTRING(menuInfo[menuIndex].menuTextID);\r
+                       resource = MAKEINTRESOURCE(menuInfo[menuIndex].iconID);\r
+                       switch (id)\r
+                       {\r
+                       case ShellMenuLock:\r
+                               // menu lock is special because it can be set to the top\r
+                               // with a separate option in the registry\r
+                               space = ((layout & MENULOCK) || ((itemStates & ITEMIS_NEEDSLOCK) && g_ShellCache.IsGetLockTop())) ? 0 : 6;\r
+                               if ((layout & MENULOCK) || ((itemStates & ITEMIS_NEEDSLOCK) && g_ShellCache.IsGetLockTop()))\r
+                               {\r
+                                       _tcscpy_s(textbuf, 255, _T("SVN "));\r
+                                       _tcscat_s(textbuf, 255, stringtablebuffer);\r
+                                       _tcscpy_s(stringtablebuffer, 255, textbuf);\r
+                               }\r
+                               break;\r
+                               // the sub menu entries are special because they're *always* on the top level menu\r
+                       case ShellSubMenuMultiple:\r
+                       case ShellSubMenuLink:\r
+                       case ShellSubMenuFolder:\r
+                       case ShellSubMenuFile:\r
+                       case ShellSubMenu:\r
+                               space = 0;\r
+                               break;\r
+                       default:\r
+                               space = layout & menuInfo[menuIndex].menuID ? 0 : 6;\r
+                               if (layout & (menuInfo[menuIndex].menuID)) \r
+                               {\r
+                                       _tcscpy_s(textbuf, 255, _T("SVN "));\r
+                                       _tcscat_s(textbuf, 255, stringtablebuffer);\r
+                                       _tcscpy_s(stringtablebuffer, 255, textbuf);\r
+                               }\r
+                               break;\r
+                       }\r
+                       return resource;\r
+               }\r
+               menuIndex++;\r
+       }\r
+       return NULL;\r
+}\r
+\r
+bool CShellExt::IsIllegalFolder(std::wstring folder, int * cslidarray)\r
+{\r
+       int i=0;\r
+       TCHAR buf[MAX_PATH];    //MAX_PATH ok, since SHGetSpecialFolderPath doesn't return the required buffer length!\r
+       LPITEMIDLIST pidl = NULL;\r
+       while (cslidarray[i])\r
+       {\r
+               ++i;\r
+               pidl = NULL;\r
+               if (SHGetFolderLocation(NULL, cslidarray[i-1], NULL, 0, &pidl)!=S_OK)\r
+                       continue;\r
+               if (!SHGetPathFromIDList(pidl, buf))\r
+               {\r
+                       // not a file system path, definitely illegal for our use\r
+                       CoTaskMemFree(pidl);\r
+                       continue;\r
+               }\r
+               CoTaskMemFree(pidl);\r
+               if (_tcslen(buf)==0)\r
+                       continue;\r
+               if (_tcscmp(buf, folder.c_str())==0)\r
+                       return true;\r
+       }\r
+       return false;\r
+}\r
+\r
+void CShellExt::InsertIgnoreSubmenus(UINT &idCmd, UINT idCmdFirst, HMENU hMenu, HMENU subMenu, UINT &indexMenu, int &indexSubMenu, unsigned __int64 topmenu, bool bShowIcons)\r
+{\r
+       HMENU ignoresubmenu = NULL;\r
+       int indexignoresub = 0;\r
+       bool bShowIgnoreMenu = false;\r
+       TCHAR maskbuf[MAX_PATH];                // MAX_PATH is ok, since this only holds a filename\r
+       TCHAR ignorepath[MAX_PATH];             // MAX_PATH is ok, since this only holds a filename\r
+       if (files_.size() == 0)\r
+               return;\r
+       UINT icon = bShowIcons ? IDI_IGNORE : 0;\r
+\r
+       std::vector<stdstring>::iterator I = files_.begin();\r
+       if (_tcsrchr(I->c_str(), '\\'))\r
+               _tcscpy_s(ignorepath, MAX_PATH, _tcsrchr(I->c_str(), '\\')+1);\r
+       else\r
+               _tcscpy_s(ignorepath, MAX_PATH, I->c_str());\r
+       if ((itemStates & ITEMIS_IGNORED)&&(ignoredprops.size() > 0))\r
+       {\r
+               // check if the item name is ignored or the mask\r
+               size_t p = 0;\r
+               while ( (p=ignoredprops.find( ignorepath,p )) != -1 )\r
+               {\r
+                       if ( (p==0 || ignoredprops[p-1]==TCHAR('\n'))\r
+                               && (p+_tcslen(ignorepath)==ignoredprops.length() || ignoredprops[p+_tcslen(ignorepath)+1]==TCHAR('\n')) )\r
+                       {\r
+                               break;\r
+                       }\r
+                       p++;\r
+               }\r
+               if (p!=-1)\r
+               {\r
+                       ignoresubmenu = CreateMenu();\r
+                       InsertMenu(ignoresubmenu, indexignoresub++, MF_BYPOSITION | MF_STRING , idCmd, ignorepath);\r
+                       stdstring verb = stdstring(ignorepath);\r
+                       myVerbsMap[verb] = idCmd - idCmdFirst;\r
+                       myVerbsMap[verb] = idCmd;\r
+                       myVerbsIDMap[idCmd - idCmdFirst] = verb;\r
+                       myVerbsIDMap[idCmd] = verb;\r
+                       myIDMap[idCmd - idCmdFirst] = ShellMenuUnIgnore;\r
+                       myIDMap[idCmd++] = ShellMenuUnIgnore;\r
+                       bShowIgnoreMenu = true;\r
+               }\r
+               _tcscpy_s(maskbuf, MAX_PATH, _T("*"));\r
+               if (_tcsrchr(ignorepath, '.'))\r
+               {\r
+                       _tcscat_s(maskbuf, MAX_PATH, _tcsrchr(ignorepath, '.'));\r
+                       p = ignoredprops.find(maskbuf);\r
+                       if ((p!=-1) &&\r
+                               ((ignoredprops.compare(maskbuf)==0) || (ignoredprops.find('\n', p)==p+_tcslen(maskbuf)+1) || (ignoredprops.rfind('\n', p)==p-1)))\r
+                       {\r
+                               if (ignoresubmenu==NULL)\r
+                                       ignoresubmenu = CreateMenu();\r
+\r
+                               InsertMenu(ignoresubmenu, indexignoresub++, MF_BYPOSITION | MF_STRING , idCmd, maskbuf);\r
+                               stdstring verb = stdstring(maskbuf);\r
+                               myVerbsMap[verb] = idCmd - idCmdFirst;\r
+                               myVerbsMap[verb] = idCmd;\r
+                               myVerbsIDMap[idCmd - idCmdFirst] = verb;\r
+                               myVerbsIDMap[idCmd] = verb;\r
+                               myIDMap[idCmd - idCmdFirst] = ShellMenuUnIgnoreCaseSensitive;\r
+                               myIDMap[idCmd++] = ShellMenuUnIgnoreCaseSensitive;\r
+                               bShowIgnoreMenu = true;\r
+                       }\r
+               }\r
+       }\r
+       else if ((itemStates & ITEMIS_IGNORED) == 0)\r
+       {\r
+               bShowIgnoreMenu = true;\r
+               ignoresubmenu = CreateMenu();\r
+               if (itemStates & ITEMIS_ONLYONE)\r
+               {\r
+                       InsertMenu(ignoresubmenu, indexignoresub++, MF_BYPOSITION | MF_STRING , idCmd, ignorepath);\r
+                       myIDMap[idCmd - idCmdFirst] = ShellMenuIgnore;\r
+                       myIDMap[idCmd++] = ShellMenuIgnore;\r
+\r
+                       _tcscpy_s(maskbuf, MAX_PATH, _T("*"));\r
+                       if (_tcsrchr(ignorepath, '.'))\r
+                       {\r
+                               _tcscat_s(maskbuf, MAX_PATH, _tcsrchr(ignorepath, '.'));\r
+                               InsertMenu(ignoresubmenu, indexignoresub++, MF_BYPOSITION | MF_STRING , idCmd, maskbuf);\r
+                               stdstring verb = stdstring(maskbuf);\r
+                               myVerbsMap[verb] = idCmd - idCmdFirst;\r
+                               myVerbsMap[verb] = idCmd;\r
+                               myVerbsIDMap[idCmd - idCmdFirst] = verb;\r
+                               myVerbsIDMap[idCmd] = verb;\r
+                               myIDMap[idCmd - idCmdFirst] = ShellMenuIgnoreCaseSensitive;\r
+                               myIDMap[idCmd++] = ShellMenuIgnoreCaseSensitive;\r
+                       }\r
+               }\r
+               else\r
+               {\r
+                       MAKESTRING(IDS_MENUIGNOREMULTIPLE);\r
+                       _stprintf_s(ignorepath, MAX_PATH, stringtablebuffer, files_.size());\r
+                       InsertMenu(ignoresubmenu, indexignoresub++, MF_BYPOSITION | MF_STRING , idCmd, ignorepath);\r
+                       stdstring verb = stdstring(ignorepath);\r
+                       myVerbsMap[verb] = idCmd - idCmdFirst;\r
+                       myVerbsMap[verb] = idCmd;\r
+                       myVerbsIDMap[idCmd - idCmdFirst] = verb;\r
+                       myVerbsIDMap[idCmd] = verb;\r
+                       myIDMap[idCmd - idCmdFirst] = ShellMenuIgnore;\r
+                       myIDMap[idCmd++] = ShellMenuIgnore;\r
+\r
+                       MAKESTRING(IDS_MENUIGNOREMULTIPLEMASK);\r
+                       _stprintf_s(ignorepath, MAX_PATH, stringtablebuffer, files_.size());\r
+                       InsertMenu(ignoresubmenu, indexignoresub++, MF_BYPOSITION | MF_STRING , idCmd, ignorepath);\r
+                       verb = stdstring(ignorepath);\r
+                       myVerbsMap[verb] = idCmd - idCmdFirst;\r
+                       myVerbsMap[verb] = idCmd;\r
+                       myVerbsIDMap[idCmd - idCmdFirst] = verb;\r
+                       myVerbsIDMap[idCmd] = verb;\r
+                       myIDMap[idCmd - idCmdFirst] = ShellMenuIgnoreCaseSensitive;\r
+                       myIDMap[idCmd++] = ShellMenuIgnoreCaseSensitive;\r
+               }\r
+       }\r
+\r
+       if (bShowIgnoreMenu)\r
+       {\r
+               MENUITEMINFO menuiteminfo;\r
+               SecureZeroMemory(&menuiteminfo, sizeof(menuiteminfo));\r
+               menuiteminfo.cbSize = sizeof(menuiteminfo);\r
+               menuiteminfo.fMask = MIIM_FTYPE | MIIM_ID | MIIM_SUBMENU | MIIM_DATA | MIIM_BITMAP | MIIM_STRING;\r
+               menuiteminfo.fType = MFT_STRING;\r
+               HBITMAP bmp = (fullver >= 0x600) ? IconToBitmapPARGB32(icon) : IconToBitmap(icon);\r
+               if (icon)\r
+                       menuiteminfo.hbmpItem = (fullver >= 0x600) ? bmp : HBMMENU_CALLBACK;\r
+               menuiteminfo.hbmpChecked = bmp;\r
+               menuiteminfo.hbmpUnchecked = bmp;\r
+               menuiteminfo.hSubMenu = ignoresubmenu;\r
+               menuiteminfo.wID = idCmd;\r
+               SecureZeroMemory(stringtablebuffer, sizeof(stringtablebuffer));\r
+               if (itemStates & ITEMIS_IGNORED)\r
+                       GetMenuTextFromResource(ShellMenuUnIgnoreSub);\r
+               else\r
+                       GetMenuTextFromResource(ShellMenuIgnoreSub);\r
+               menuiteminfo.dwTypeData = stringtablebuffer;\r
+               menuiteminfo.cch = (UINT)min(_tcslen(menuiteminfo.dwTypeData), UINT_MAX);\r
+\r
+               InsertMenuItem((topmenu & MENUIGNORE) ? hMenu : subMenu, (topmenu & MENUIGNORE) ? indexMenu++ : indexSubMenu++, TRUE, &menuiteminfo);\r
+               if (itemStates & ITEMIS_IGNORED)\r
+               {\r
+                       myIDMap[idCmd - idCmdFirst] = ShellMenuUnIgnoreSub;\r
+                       myIDMap[idCmd++] = ShellMenuUnIgnoreSub;\r
+               }\r
+               else\r
+               {\r
+                       myIDMap[idCmd - idCmdFirst] = ShellMenuIgnoreSub;\r
+                       myIDMap[idCmd++] = ShellMenuIgnoreSub;\r
+               }\r
+       }\r
+}\r
+\r
+HBITMAP CShellExt::IconToBitmapPARGB32(UINT uIcon)\r
+{\r
+       std::map<UINT, HBITMAP>::iterator bitmap_it = bitmaps.lower_bound(uIcon);\r
+       if (bitmap_it != bitmaps.end() && bitmap_it->first == uIcon)\r
+               return bitmap_it->second;\r
+\r
+       HICON hIcon = (HICON)LoadImage(g_hResInst, MAKEINTRESOURCE(uIcon), IMAGE_ICON, 16, 16, LR_DEFAULTCOLOR);\r
+       if (!hIcon)\r
+               return NULL;\r
+\r
+       if (pfnBeginBufferedPaint == NULL || pfnEndBufferedPaint == NULL || pfnGetBufferedPaintBits == NULL)\r
+               return NULL;\r
+\r
+       SIZE sizIcon;\r
+       sizIcon.cx = GetSystemMetrics(SM_CXSMICON);\r
+       sizIcon.cy = GetSystemMetrics(SM_CYSMICON);\r
+\r
+       RECT rcIcon;\r
+       SetRect(&rcIcon, 0, 0, sizIcon.cx, sizIcon.cy);\r
+       HBITMAP hBmp = NULL;\r
+\r
+       HDC hdcDest = CreateCompatibleDC(NULL);\r
+       if (hdcDest)\r
+       {\r
+               if (SUCCEEDED(Create32BitHBITMAP(hdcDest, &sizIcon, NULL, &hBmp)))\r
+               {\r
+                       HBITMAP hbmpOld = (HBITMAP)SelectObject(hdcDest, hBmp);\r
+                       if (hbmpOld)\r
+                       {\r
+                               BLENDFUNCTION bfAlpha = { AC_SRC_OVER, 0, 255, AC_SRC_ALPHA };\r
+                               BP_PAINTPARAMS paintParams = {0};\r
+                               paintParams.cbSize = sizeof(paintParams);\r
+                               paintParams.dwFlags = BPPF_ERASE;\r
+                               paintParams.pBlendFunction = &bfAlpha;\r
+\r
+                               HDC hdcBuffer;\r
+                               HPAINTBUFFER hPaintBuffer = pfnBeginBufferedPaint(hdcDest, &rcIcon, BPBF_DIB, &paintParams, &hdcBuffer);\r
+                               if (hPaintBuffer)\r
+                               {\r
+                                       if (DrawIconEx(hdcBuffer, 0, 0, hIcon, sizIcon.cx, sizIcon.cy, 0, NULL, DI_NORMAL))\r
+                                       {\r
+                                               // If icon did not have an alpha channel we need to convert buffer to PARGB\r
+                                               ConvertBufferToPARGB32(hPaintBuffer, hdcDest, hIcon, sizIcon);\r
+                                       }\r
+\r
+                                       // This will write the buffer contents to the destination bitmap\r
+                                       pfnEndBufferedPaint(hPaintBuffer, TRUE);\r
+                               }\r
+\r
+                               SelectObject(hdcDest, hbmpOld);\r
+                       }\r
+               }\r
+\r
+               DeleteDC(hdcDest);\r
+       }\r
+\r
+       DestroyIcon(hIcon);\r
+\r
+       if(hBmp)\r
+               bitmaps.insert(bitmap_it, std::make_pair(uIcon, hBmp));\r
+       return hBmp;\r
+}\r
+\r
+HRESULT CShellExt::Create32BitHBITMAP(HDC hdc, const SIZE *psize, __deref_opt_out void **ppvBits, __out HBITMAP* phBmp)\r
+{\r
+       *phBmp = NULL;\r
+\r
+       BITMAPINFO bmi;\r
+       ZeroMemory(&bmi, sizeof(bmi));\r
+       bmi.bmiHeader.biSize = sizeof(BITMAPINFOHEADER);\r
+       bmi.bmiHeader.biPlanes = 1;\r
+       bmi.bmiHeader.biCompression = BI_RGB;\r
+\r
+       bmi.bmiHeader.biWidth = psize->cx;\r
+       bmi.bmiHeader.biHeight = psize->cy;\r
+       bmi.bmiHeader.biBitCount = 32;\r
+\r
+       HDC hdcUsed = hdc ? hdc : GetDC(NULL);\r
+       if (hdcUsed)\r
+       {\r
+               *phBmp = CreateDIBSection(hdcUsed, &bmi, DIB_RGB_COLORS, ppvBits, NULL, 0);\r
+               if (hdc != hdcUsed)\r
+               {\r
+                       ReleaseDC(NULL, hdcUsed);\r
+               }\r
+       }\r
+       return (NULL == *phBmp) ? E_OUTOFMEMORY : S_OK;\r
+}\r
+\r
+HRESULT CShellExt::ConvertBufferToPARGB32(HPAINTBUFFER hPaintBuffer, HDC hdc, HICON hicon, SIZE& sizIcon)\r
+{\r
+       RGBQUAD *prgbQuad;\r
+       int cxRow;\r
+       HRESULT hr = pfnGetBufferedPaintBits(hPaintBuffer, &prgbQuad, &cxRow);\r
+       if (SUCCEEDED(hr))\r
+       {\r
+               ARGB *pargb = reinterpret_cast<ARGB *>(prgbQuad);\r
+               if (!HasAlpha(pargb, sizIcon, cxRow))\r
+               {\r
+                       ICONINFO info;\r
+                       if (GetIconInfo(hicon, &info))\r
+                       {\r
+                               if (info.hbmMask)\r
+                               {\r
+                                       hr = ConvertToPARGB32(hdc, pargb, info.hbmMask, sizIcon, cxRow);\r
+                               }\r
+\r
+                               DeleteObject(info.hbmColor);\r
+                               DeleteObject(info.hbmMask);\r
+                       }\r
+               }\r
+       }\r
+\r
+       return hr;\r
+}\r
+\r
+bool CShellExt::HasAlpha(__in ARGB *pargb, SIZE& sizImage, int cxRow)\r
+{\r
+       ULONG cxDelta = cxRow - sizImage.cx;\r
+       for (ULONG y = sizImage.cy; y; --y)\r
+       {\r
+               for (ULONG x = sizImage.cx; x; --x)\r
+               {\r
+                       if (*pargb++ & 0xFF000000)\r
+                       {\r
+                               return true;\r
+                       }\r
+               }\r
+\r
+               pargb += cxDelta;\r
+       }\r
+\r
+       return false;\r
+}\r
+\r
+HRESULT CShellExt::ConvertToPARGB32(HDC hdc, __inout ARGB *pargb, HBITMAP hbmp, SIZE& sizImage, int cxRow)\r
+{\r
+       BITMAPINFO bmi;\r
+       ZeroMemory(&bmi, sizeof(bmi));\r
+       bmi.bmiHeader.biSize = sizeof(BITMAPINFOHEADER);\r
+       bmi.bmiHeader.biPlanes = 1;\r
+       bmi.bmiHeader.biCompression = BI_RGB;\r
+\r
+       bmi.bmiHeader.biWidth = sizImage.cx;\r
+       bmi.bmiHeader.biHeight = sizImage.cy;\r
+       bmi.bmiHeader.biBitCount = 32;\r
+\r
+       HRESULT hr = E_OUTOFMEMORY;\r
+       HANDLE hHeap = GetProcessHeap();\r
+       void *pvBits = HeapAlloc(hHeap, 0, bmi.bmiHeader.biWidth * 4 * bmi.bmiHeader.biHeight);\r
+       if (pvBits)\r
+       {\r
+               hr = E_UNEXPECTED;\r
+               if (GetDIBits(hdc, hbmp, 0, bmi.bmiHeader.biHeight, pvBits, &bmi, DIB_RGB_COLORS) == bmi.bmiHeader.biHeight)\r
+               {\r
+                       ULONG cxDelta = cxRow - bmi.bmiHeader.biWidth;\r
+                       ARGB *pargbMask = static_cast<ARGB *>(pvBits);\r
+\r
+                       for (ULONG y = bmi.bmiHeader.biHeight; y; --y)\r
+                       {\r
+                               for (ULONG x = bmi.bmiHeader.biWidth; x; --x)\r
+                               {\r
+                                       if (*pargbMask++)\r
+                                       {\r
+                                               // transparent pixel\r
+                                               *pargb++ = 0;\r
+                                       }\r
+                                       else\r
+                                       {\r
+                                               // opaque pixel\r
+                                               *pargb++ |= 0xFF000000;\r
+                                       }\r
+                               }\r
+\r
+                               pargb += cxDelta;\r
+                       }\r
+\r
+                       hr = S_OK;\r
+               }\r
+\r
+               HeapFree(hHeap, 0, pvBits);\r
+       }\r
+\r
+       return hr;\r
+}\r
+\r
diff --git a/TortoiseShell/Documentation.h b/TortoiseShell/Documentation.h
new file mode 100644 (file)
index 0000000..012385d
--- /dev/null
@@ -0,0 +1,416 @@
+/**\r
+ * \mainpage TortoiseSVN\r
+ * \section introduction Introduction\r
+ * TortoiseSVN is a windows shell integration for the Subversion\r
+ * source versioning system. Subversion is the successor\r
+ * of the famous CVS. See http://subversion.tigris.org for\r
+ * more information on Subversion.\r
+ *\r
+ * TortoiseSVN was inspired by the similar program TortoiseCVS.\r
+ * \r
+ * With TortoiseSVN you can use Subversion directly from the\r
+ * Windows Explorer. The Subversion status of your project\r
+ * files are clearly visible and all commands Subversion\r
+ * provides are accessible directly from the Explorer Context-Menu\r
+ * (right-click).\r
+ *\r
+ * \section Requirements Requirements\r
+ * TortoiseSVN runs under Win2k and later.\r
+ * You also need at least Internet Explorer Version 5 or higher.\r
+ *\r
+ * \section Installation Installation\r
+ * TortoiseSVN comes with an installer. Just run the installer and follow\r
+ * the simple steps of the wizard. You may need to restart your computer\r
+ * to get TortoiseSVN to work, depending on your registry settings. If you're\r
+ * not sure, fire up the explorer, right click on a folder and check if\r
+ * the TortoiseSVN menus are there.\r
+ *\r
+ * \section Sourcecode Source code\r
+ * The full source code of TortoiseSVN is available at http://tortoisesvn.net.\r
+ * \r
+ * For information on how to build TortoiseSVN from the source code see \ref build\r
+ *\r
+ * \section Internals Internals\r
+ * TortoiseSVN is a shell extension. All commands and dialogs are started by\r
+ * using the shell context menu on files and folders.\r
+ *\r
+ * The shell extension part is separate from the main application to reduce\r
+ * the memory use in the shell. The shell extension only does what's absolutely\r
+ * necessary and then creates a new process of the main application to do the\r
+ * real work. The main application is TortoiseProc. The shell passes all the\r
+ * information to TortoiseProc via command line switches and temporary files.\r
+ *\r
+ * To avoid loading the whole TortoiseShell dll if it isn't really wanted (e.g.,\r
+ * in applications other than the explorer itself), there's a stub dll which\r
+ * is registered in the shell as the extension. That stub dll then loads the\r
+ * TortoiseShell dll if required.\r
+ */\r
+\r
+/**\r
+ * \page licensesvn Subversion license\r
+ * <H1>Subversion License</H1>\r
+ * ================================================================\r
+ * Copyright (c) 2004 CollabNet.  All rights reserved.\r
+ * \r
+ * Redistribution and use in source and binary forms, with or without\r
+ * modification, are permitted provided that the following conditions are\r
+ * met:\r
+ * \r
+ * 1. Redistributions of source code must retain the above copyright\r
+ * notice, this list of conditions and the following disclaimer.\r
+ * \r
+ * 2. Redistributions in binary form must reproduce the above copyright\r
+ * notice, this list of conditions and the following disclaimer in the\r
+ * documentation and/or other materials provided with the distribution.\r
+ * \r
+ * 3. The end-user documentation included with the redistribution, if\r
+ * any, must include the following acknowledgment: "This product includes\r
+ * software developed by CollabNet (http://www.Collab.Net/)."\r
+ * Alternately, this acknowledgment may appear in the software itself, if\r
+ * and wherever such third-party acknowledgments normally appear.\r
+ * \r
+ * 4. The hosted project names must not be used to endorse or promote\r
+ * products derived from this software without prior written\r
+ * permission. For written permission, please contact info@collab.net.\r
+ * \r
+ * 5. Products derived from this software may not use the "Tigris" name\r
+ * nor may "Tigris" appear in their names without prior written\r
+ * permission of CollabNet.\r
+ * \r
+ * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED\r
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF\r
+ * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.\r
+ * IN NO EVENT SHALL COLLABNET OR ITS CONTRIBUTORS BE LIABLE FOR ANY\r
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL\r
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE\r
+ * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS\r
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER\r
+ * IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR\r
+ * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF\r
+ * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\r
+ *\r
+ * ====================================================================\r
+ * \r
+ * This software consists of voluntary contributions made by many\r
+ * individuals on behalf of CollabNet.\r
+ */\r
+\r
+\r
+/**\r
+ * \page license TortoiseSVN license\r
+ * <H1>GNU General Public License</H1>\r
+ * also available at http://www.gnu.org/licenses/gpl.html\r
+ * \n\r
+ * Version 2, June 1991\r
+ * \n\r
+ * Copyright (C) 1989, 1991 Free Software Foundation, Inc.  \r
+ * \n\r
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.\r
+ * \n\r
+ * Everyone is permitted to copy and distribute verbatim copies\r
+ * of this license document, but changing it is not allowed.\r
+ * \n\r
+ * <H2>Preamble</H2>\r
+ * The licenses for most software are designed to take away your \r
+ * freedom to share and change it. By contrast, the GNU General \r
+ * Public License is intended to guarantee your freedom to share and \r
+ * change free software--to make sure the software is free for all its \r
+ * users. This General Public License applies to most of the Free \r
+ * Software Foundation's software and to any other program whose authors \r
+ * commit to using it. (Some other Free Software Foundation software is \r
+ * covered by the GNU Library General Public License instead.) You can \r
+ * apply it to your programs, too. \r
+ * \n\r
+ * When we speak of free software, we are referring to freedom, not price. \r
+ * Our General Public Licenses are designed to make sure that you have the \r
+ * freedom to distribute copies of free software (and charge for this service \r
+ * if you wish), that you receive source code or can get it if you want it, \r
+ * that you can change the software or use pieces of it in new free programs; \r
+ * and that you know you can do these things. \r
+ * \n\r
+ * To protect your rights, we need to make restrictions that forbid anyone to \r
+ * deny you these rights or to ask you to surrender the rights. These restrictions \r
+ * translate to certain responsibilities for you if you distribute copies \r
+ * of the software, or if you modify it. \r
+ * \n\r
+ * For example, if you distribute copies of such a program, whether gratis or for \r
+ * a fee, you must give the recipients all the rights that you have. You must make \r
+ * sure that they, too, receive or can get the source code. And you must show them \r
+ * these terms so they know their rights. \r
+ * \n\r
+ * We protect your rights with two steps: (1) copyright the software, and (2) offer \r
+ * you this license which gives you legal permission to copy, distribute and/or \r
+ * modify the software. \r
+ * \n\r
+ * Also, for each author's protection and ours, we want to make certain that \r
+ * everyone understands that there is no warranty for this free software. If \r
+ * the software is modified by someone else and passed on, we want its recipients \r
+ * to know that what they have is not the original, so that any problems introduced \r
+ * by others will not reflect on the original authors' reputations. \r
+ * \n\r
+ * Finally, any free program is threatened constantly by software patents. We wish \r
+ * to avoid the danger that redistributors of a free program will individually \r
+ * obtain patent licenses, in effect making the program proprietary. To prevent \r
+ * this, we have made it clear that any patent must be licensed for everyone's \r
+ * free use or not licensed at all. \r
+ * \n\r
+ * The precise terms and conditions for copying, distribution and modification follow. \r
+ * \r
+ * <H1>TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION</H1>\r
+ * -# This License applies to any program or other work which contains a notice \r
+ * placed by the copyright holder saying it may be distributed under the terms of \r
+ * this General Public License. The "Program", below, refers to any such program \r
+ * or work, and a "work based on the Program" means either the Program or any \r
+ * derivative work under copyright law: that is to say, a work containing the \r
+ * Program or a portion of it, either verbatim or with modifications and/or \r
+ * translated into another language. (Hereinafter, translation is included without\r
+ * limitation in the term "modification".) Each licensee is addressed as "you". \r
+ * \n\r
+ * Activities other than copying, distribution and modification are not covered \r
+ * by this License; they are outside its scope. The act of running the Program \r
+ * is not restricted, and the output from the Program is covered only if its \r
+ * contents constitute a work based on the Program (independent of having been \r
+ * made by running the Program). Whether that is true depends on what the Program does. \r
+ * -# You may copy and distribute verbatim copies of the Program's source code \r
+ * as you receive it, in any medium, provided that you conspicuously and \r
+ * appropriately publish on each copy an appropriate copyright notice and \r
+ * disclaimer of warranty; keep intact all the notices that refer to this \r
+ * License and to the absence of any warranty; and give any other recipients \r
+ * of the Program a copy of this License along with the Program. \r
+ * \n\r
+ * You may charge a fee for the physical act of transferring a copy, and you \r
+ * may at your option offer warranty protection in exchange for a fee. \r
+ * -# You may modify your copy or copies of the Program or any portion of it, \r
+ * thus forming a work based on the Program, and copy and distribute such \r
+ * modifications or work under the terms of Section 1 above, provided that you \r
+ * also meet all of these conditions: \r
+ *   - You must cause the modified files to carry prominent notices stating \r
+ *       that you changed the files and the date of any change. \r
+ *   - You must cause any work that you distribute or publish, that in whole \r
+ *   or in part contains or is derived from the Program or any part thereof, \r
+ *   to be licensed as a whole at no charge to all third parties under the terms \r
+ *   of this License. \r
+ *   - If the modified program normally reads commands interactively when run,\r
+ *   you must cause it, when started running for such interactive use in the most \r
+ *   ordinary way, to print or display an announcement including an appropriate \r
+ *   copyright notice and a notice that there is no warranty (or else, saying that \r
+ *   you provide a warranty) and that users may redistribute the program under these \r
+ *   conditions, and telling the user how to view a copy of this License. (Exception: \r
+ *   if the Program itself is interactive but does not normally print such an \r
+ *   announcement, your work based on the Program is not required to print an \r
+ *   announcement.) \r
+ *   .\r
+ *   These requirements apply to the modified work as a whole. If identifiable \r
+ *   sections of that work are not derived from the Program, and can be reasonably \r
+ *   considered independent and separate works in themselves, then this License, \r
+ *   and its terms, do not apply to those sections when you distribute them as \r
+ *   separate works. But when you distribute the same sections as part of a whole \r
+ *   which is a work based on the Program, the distribution of the whole must be \r
+ *   on the terms of this License, whose permissions for other licensees extend \r
+ *   to the entire whole, and thus to each and every part regardless of who wrote it. \r
+ *   \n\r
+ *   Thus, it is not the intent of this section to claim rights or contest your \r
+ *   rights to work written entirely by you; rather, the intent is to exercise \r
+ *   the right to control the distribution of derivative or collective works \r
+ *   based on the Program. \r
+ *   \n\r
+ *   In addition, mere aggregation of another work not based on the Program with \r
+ *   the Program (or with a work based on the Program) on a volume of a storage \r
+ *   or distribution medium does not bring the other work under the scope of \r
+ *   this License. \r
+ * -# You may copy and distribute the Program (or a work based on it, under Section 2)\r
+ * in object code or executable form under the terms of Sections 1 and 2 above \r
+ * provided that you also do one of the following: \r
+ *   - Accompany it with the complete corresponding machine-readable source code, \r
+ *   which must be distributed under the terms of Sections 1 and 2 above on a \r
+ *   medium customarily used for software interchange; or, \r
+ *   - Accompany it with a written offer, valid for at least three years, \r
+ *   to give any third party, for a charge no more than your cost of physically \r
+ *   performing source distribution, a complete machine-readable copy of the \r
+ *   corresponding source code, to be distributed under the terms of Sections 1 \r
+ *   and 2 above on a medium customarily used for software interchange; or, \r
+ *   - Accompany it with the information you received as to the offer to distribute \r
+ *   corresponding source code. (This alternative is allowed only for noncommercial \r
+ *   distribution and only if you received the program in object code or executable \r
+ *   form with such an offer, in accord with Subsection b above.) \r
+ *   .\r
+ *   The source code for a work means the preferred form of the work for making \r
+ *   modifications to it. For an executable work, complete source code means all \r
+ *   the source code for all modules it contains, plus any associated interface \r
+ *   definition files, plus the scripts used to control compilation and installation \r
+ *   of the executable. However, as a special exception, the source code distributed \r
+ *   need not include anything that is normally distributed (in either source or \r
+ *   binary form) with the major components (compiler, kernel, and so on) of the \r
+ *   operating system on which the executable runs, unless that component itself \r
+ *   accompanies the executable. \r
+ *   \n\r
+ *   If distribution of executable or object code is made by offering access to \r
+ *   copy from a designated place, then offering equivalent access to copy the \r
+ *   source code from the same place counts as distribution of the source code, \r
+ *   even though third parties are not compelled to copy the source along with \r
+ *   the object code. \r
+ * -# You may not copy, modify, sublicense, or distribute the Program except \r
+ * as expressly provided under this License. Any attempt otherwise to copy,\r
+ * modify, sublicense or distribute the Program is void, and will automatically \r
+ * terminate your rights under this License. However, parties who have received \r
+ * copies, or rights, from you under this License will not have their licenses \r
+ * terminated so long as such parties remain in full compliance. \r
+ * -# You are not required to accept this License, since you have not signed it. \r
+ * However, nothing else grants you permission to modify or distribute the Program \r
+ * or its derivative works. These actions are prohibited by law if you do not \r
+ * accept this License. Therefore, by modifying or distributing the Program \r
+ * (or any work based on the Program), you indicate your acceptance of this \r
+ * License to do so, and all its terms and conditions for copying, distributing \r
+ * or modifying the Program or works based on it. \r
+ * -# Each time you redistribute the Program (or any work based on the Program), \r
+ * the recipient automatically receives a license from the original licensor to copy, \r
+ * distribute or modify the Program subject to these terms and conditions. You may \r
+ * not impose any further restrictions on the recipients' exercise of the rights \r
+ * granted herein. You are not responsible for enforcing compliance by third \r
+ * parties to this License. \r
+ * -# If, as a consequence of a court judgment or allegation of patent infringement \r
+ * or for any other reason (not limited to patent issues), conditions are imposed \r
+ * on you (whether by court order, agreement or otherwise) that contradict the \r
+ * conditions of this License, they do not excuse you from the conditions of this \r
+ * License. If you cannot distribute so as to satisfy simultaneously your obligations \r
+ * under this License and any other pertinent obligations, then as a consequence you \r
+ * may not distribute the Program at all. For example, if a patent license would not \r
+ * permit royalty-free redistribution of the Program by all those who receive copies \r
+ * directly or indirectly through you, then the only way you could satisfy both it and \r
+ * this License would be to refrain entirely from distribution of the Program. \r
+ * \n\r
+ * If any portion of this section is held invalid or unenforceable under any particular \r
+ * circumstance, the balance of the section is intended to apply and the section as a \r
+ * whole is intended to apply in other circumstances. \r
+ * \n\r
+ * It is not the purpose of this section to induce you to infringe any patents or other \r
+ * property right claims or to contest validity of any such claims; this section has \r
+ * the sole purpose of protecting the integrity of the free software distribution system, \r
+ * which is implemented by public license practices. Many people have made generous \r
+ * contributions to the wide range of software distributed through that system in reliance \r
+ * on consistent application of that system; it is up to the author/donor to decide if he \r
+ * or she is willing to distribute software through any other system and a licensee cannot \r
+ * impose that choice. \r
+ * \n\r
+ * This section is intended to make thoroughly clear what is believed to be a consequence \r
+ * of the rest of this License. \r
+ * -# If the distribution and/or use of the Program is restricted in certain countries \r
+ * either by patents or by copyrighted interfaces, the original copyright holder who \r
+ * places the Program under this License may add an explicit geographical distribution \r
+ * limitation excluding those countries, so that distribution is permitted only in or \r
+ * among countries not thus excluded. In such case, this License incorporates the \r
+ * limitation as if written in the body of this License. \r
+ * -# The Free Software Foundation may publish revised and/or new versions of the \r
+ * General Public License from time to time. Such new versions will be similar in \r
+ * spirit to the present version, but may differ in detail to address new problems \r
+ * or concerns. \r
+ * \n\r
+ * Each version is given a distinguishing version number. If the Program specifies \r
+ * a version number of this License which applies to it and "any later version", \r
+ * you have the option of following the terms and conditions either of that version \r
+ * or of any later version published by the Free Software Foundation. If the Program \r
+ * does not specify a version number of this License, you may choose any version \r
+ * ever published by the Free Software Foundation. \r
+ * -# If you wish to incorporate parts of the Program into other free programs whose \r
+ * distribution conditions are different, write to the author to ask for permission. \r
+ * For software which is copyrighted by the Free Software Foundation, write to the \r
+ * Free Software Foundation; we sometimes make exceptions for this. Our decision \r
+ * will be guided by the two goals of preserving the free status of all derivatives \r
+ * of our free software and of promoting the sharing and reuse of software generally. \r
+ * <H2>NO WARRANTY</H2>\r
+ * -# BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY FOR THE \r
+ * PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN OTHERWISE STATED \r
+ * IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES PROVIDE THE PROGRAM "AS IS" \r
+ * WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED \r
+ * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. \r
+ * THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD \r
+ * THE PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING, REPAIR \r
+ * OR CORRECTION. \r
+ * -# IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING WILL ANY\r
+ * COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR REDISTRIBUTE THE PROGRAM \r
+ * AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY GENERAL, SPECIAL, \r
+ * INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE USE OR INABILITY TO USE THE \r
+ * PROGRAM (INCLUDING BUT NOT LIMITED TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE \r
+ * OR LOSSES SUSTAINED BY YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE \r
+ * WITH ANY OTHER PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF \r
+ * THE POSSIBILITY OF SUCH DAMAGES.\r
+ *\r
+ */\r
+\r
+/**\r
+ * \defgroup TortoiseShell TortoiseShell\r
+ * Windows-Shell integration of TortoiseSVN.\r
+ * This project links to a COM object implementing all required\r
+ * interfaces a shell extension needs.\r
+ * The shell extension draws the overlay icons, provides the right-click menu,\r
+ * the property sheet and the SVN column (in Win2k and later).\r
+ */\r
+\r
+/**\r
+ * \defgroup TortoiseProc TortoiseProc\r
+ * Main program of TortoiseSVN. TortoiseShell calls this program\r
+ * to execute the required commands, the commands are specified in\r
+ * the command line.\r
+ */\r
+\r
+/**\r
+ * \defgroup TortoiseMerge TortoiseMerge\r
+ * A separate Diff/Merge program, shipped with TortoiseSVN.\r
+ */\r
+\r
+/**\r
+ * \defgroup TortoiseBlame TortoiseBlame\r
+ * A viewer for Subversion blame information.\r
+ */\r
+\r
+/**\r
+ * \defgroup TortoiseIDiff TortoiseIDiff\r
+ * An image diff viewer.\r
+ */\r
+\r
+/**\r
+ * \defgroup TortoiseUDiff TortoiseUDiff\r
+ * An unified diff viewer.\r
+ */\r
+\r
+/**\r
+ * \defgroup ResText ResText\r
+ * An utility to extract resource strings from executable files and apply\r
+ * translated strings back to them. Used for translating.\r
+ */\r
+\r
+/**\r
+ * \defgroup SubWCRev SubWCRev\r
+ * A tool to get information about a Subversion working copy.\r
+ */\r
+\r
+/**\r
+ * \defgroup Utils Utils\r
+ * Utility classes and functions not specific to TortoiseSVN, i.e. they\r
+ * could be used in other programs too.\r
+ */\r
+\r
+/**\r
+ * \defgroup SVN SVN\r
+ * Wrappers for the Subversion API.\r
+ */\r
+\r
+/**\r
+ * \defgroup TSVNCache TSVNCache\r
+ * Cache for Subversion status of files and folders.\r
+ */\r
+\r
+\r
+\r
+\r
+\r
+\r
+\r
+\r
+\r
+\r
+\r
+\r
+\r
+\r
+ */\r
diff --git a/TortoiseShell/Globals.h b/TortoiseShell/Globals.h
new file mode 100644 (file)
index 0000000..6612edb
--- /dev/null
@@ -0,0 +1,102 @@
+// TortoiseSVN - a Windows shell extension for easy version control\r
+\r
+// Copyright (C) 2003-2008 - TortoiseSVN\r
+\r
+// This program is free software; you can redistribute it and/or\r
+// modify it under the terms of the GNU General Public License\r
+// as published by the Free Software Foundation; either version 2\r
+// of the License, or (at your option) any later version.\r
+\r
+// This program is distributed in the hope that it will be useful,\r
+// but WITHOUT ANY WARRANTY; without even the implied warranty of\r
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\r
+// GNU General Public License for more details.\r
+\r
+// You should have received a copy of the GNU General Public License\r
+// along with this program; if not, write to the Free Software Foundation,\r
+// 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.\r
+//\r
+#pragma once\r
+\r
+#define MENUCHECKOUT           0x0000000000000001\r
+#define MENUUPDATE                     0x0000000000000002\r
+#define MENUCOMMIT                     0x0000000000000004\r
+#define MENUADD                                0x0000000000000008\r
+#define MENUREVERT                     0x0000000000000010\r
+#define MENUCLEANUP                    0x0000000000000020\r
+#define MENURESOLVE                    0x0000000000000040\r
+#define MENUSWITCH                     0x0000000000000080\r
+#define MENUIMPORT                     0x0000000000000100\r
+#define MENUEXPORT                     0x0000000000000200\r
+#define MENUCREATEREPOS                0x0000000000000400\r
+#define MENUCOPY                       0x0000000000000800\r
+#define MENUMERGE                      0x0000000000001000\r
+#define MENUREMOVE                     0x0000000000002000\r
+#define MENURENAME                     0x0000000000004000\r
+#define MENUUPDATEEXT          0x0000000000008000\r
+#define MENUDIFF                       0x0000000000010000\r
+#define MENULOG                                0x0000000000020000\r
+#define MENUCONFLICTEDITOR     0x0000000000040000\r
+#define MENURELOCATE           0x0000000000080000\r
+#define MENUSHOWCHANGED                0x0000000000100000\r
+#define MENUIGNORE                     0x0000000000200000\r
+#define MENUREPOBROWSE         0x0000000000400000\r
+#define MENUBLAME                      0x0000000000800000\r
+#define MENUCREATEPATCH                0x0000000001000000\r
+#define MENUAPPLYPATCH         0x0000000002000000\r
+#define MENUREVISIONGRAPH      0x0000000004000000\r
+#define MENULOCK                       0x0000000008000000\r
+#define MENUUNLOCK                     0x0000000010000000\r
+#define MENUPROPERTIES         0x0000000020000000\r
+#define MENUURLDIFF                    0x0000000040000000\r
+#define MENUDELUNVERSIONED     0x0000000080000000\r
+#define MENUMERGEALL           0x0000000100000000\r
+#define MENUPREVDIFF           0x0000000200000000\r
+#define MENUCLIPPASTE          0x0000000400000000\r
+\r
+#define MENUSETTINGS           0x2000000000000000\r
+#define MENUHELP                       0x4000000000000000\r
+#define MENUABOUT                      0x8000000000000000\r
+\r
+/**\r
+ * \ingroup TortoiseShell\r
+ * Since we need an own COM-object for every different\r
+ * Icon-Overlay implemented this enum defines which class\r
+ * is used.\r
+ */\r
+enum FileState\r
+{\r
+    FileStateUncontrolled,\r
+    FileStateVersioned,\r
+    FileStateModified,\r
+    FileStateConflict,\r
+       FileStateDeleted,\r
+       FileStateReadOnly,\r
+       FileStateLockedOverlay,\r
+       FileStateAddedOverlay,\r
+       FileStateIgnoredOverlay,\r
+       FileStateUnversionedOverlay,\r
+       FileStateDropHandler,\r
+       FileStateInvalid\r
+};\r
+\r
+\r
+#define ITEMIS_ONLYONE                         0x00000001\r
+#define ITEMIS_EXTENDED                                0x00000002\r
+#define ITEMIS_INSVN                           0x00000004\r
+#define ITEMIS_CONFLICTED                      0x00000008\r
+#define ITEMIS_FOLDER                          0x00000010\r
+#define ITEMIS_FOLDERINSVN                     0x00000020\r
+#define ITEMIS_NORMAL                          0x00000040\r
+#define ITEMIS_IGNORED                         0x00000080\r
+#define ITEMIS_INVERSIONEDFOLDER       0x00000100\r
+#define ITEMIS_ADDED                           0x00000200\r
+#define ITEMIS_DELETED                         0x00000400\r
+#define ITEMIS_LOCKED                          0x00000800\r
+#define ITEMIS_PATCHFILE                       0x00001000\r
+// #define ITEMIS_SHORTCUT                     0x00002000 //unused\r
+#define ITEMIS_NEEDSLOCK                       0x00004000\r
+#define ITEMIS_PATCHINCLIPBOARD                0x00008000\r
+#define ITEMIS_PATHINCLIPBOARD      0x00010000\r
+#define ITEMIS_TWO                                     0x00020000\r
+\r
diff --git a/TortoiseShell/Guids.h b/TortoiseShell/Guids.h
new file mode 100644 (file)
index 0000000..50d1356
--- /dev/null
@@ -0,0 +1,54 @@
+// TortoiseSVN - a Windows shell extension for easy version control\r
+\r
+// Copyright (C) 2003-2008 - Stefan Kueng\r
+\r
+// This program is free software; you can redistribute it and/or\r
+// modify it under the terms of the GNU General Public License\r
+// as published by the Free Software Foundation; either version 2\r
+// of the License, or (at your option) any later version.\r
+\r
+// This program is distributed in the hope that it will be useful,\r
+// but WITHOUT ANY WARRANTY; without even the implied warranty of\r
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\r
+// GNU General Public License for more details.\r
+\r
+// You should have received a copy of the GNU General Public License\r
+// along with this program; if not, write to the Free Software Foundation,\r
+// 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.\r
+//\r
+\r
+\r
+// The class IDs of these Shell extension class.\r
+//\r
+// class ids: \r
+//\r
+// 30351346-7B7D-4FCC-81B4-1E394CA267EB\r
+// 30351347-7B7D-4FCC-81B4-1E394CA267EB\r
+// 30351348-7B7D-4FCC-81B4-1E394CA267EB\r
+// 30351349-7B7D-4FCC-81B4-1E394CA267EB\r
+// 3035134A-7B7D-4FCC-81B4-1E394CA267EB\r
+// 3035134B-7B7D-4FCC-81B4-1E394CA267EB\r
+// 3035134C-7B7D-4FCC-81B4-1E394CA267EB\r
+// 3035134D-7B7D-4FCC-81B4-1E394CA267EB\r
+// 3035134E-7B7D-4FCC-81B4-1E394CA267EB\r
+// 3035134F-7B7D-4FCC-81B4-1E394CA267EB\r
+//\r
+//\r
+// NOTE!!!  If you use this shell extension as a starting point, \r
+//          you MUST change the GUID below.  Simply run UUIDGEN.EXE\r
+//          to generate a new GUID.\r
+//\r
+\r
+DEFINE_GUID(CLSID_TortoiseSVN_UPTODATE,0x30351346, 0x7b7d, 0x4fcc, 0x81, 0xb4, 0x1e, 0x39, 0x4c, 0xa2, 0x67, 0xeb);\r
+DEFINE_GUID(CLSID_TortoiseSVN_MODIFIED,0x30351347, 0x7b7d, 0x4fcc, 0x81, 0xb4, 0x1e, 0x39, 0x4c, 0xa2, 0x67, 0xeb);\r
+DEFINE_GUID(CLSID_TortoiseSVN_CONFLICTING,0x30351348, 0x7b7d, 0x4fcc, 0x81, 0xb4, 0x1e, 0x39, 0x4c, 0xa2, 0x67, 0xeb);\r
+DEFINE_GUID(CLSID_TortoiseSVN_UNCONTROLLED,0x30351349, 0x7b7d, 0x4fcc, 0x81, 0xb4, 0x1e, 0x39, 0x4c, 0xa2, 0x67, 0xeb);\r
+DEFINE_GUID(CLSID_TortoiseSVN_DROPHANDLER,0x3035134a, 0x7b7d, 0x4fcc, 0x81, 0xb4, 0x1e, 0x39, 0x4c, 0xa2, 0x67, 0xeb);\r
+DEFINE_GUID(CLSID_TortoiseSVN_READONLY,0x3035134b, 0x7b7d, 0x4fcc, 0x81, 0xb4, 0x1e, 0x39, 0x4c, 0xa2, 0x67, 0xeb);\r
+DEFINE_GUID(CLSID_TortoiseSVN_DELETED,0x3035134c, 0x7b7d, 0x4fcc, 0x81, 0xb4, 0x1e, 0x39, 0x4c, 0xa2, 0x67, 0xeb);\r
+DEFINE_GUID(CLSID_TortoiseSVN_LOCKED,0x3035134d, 0x7b7d, 0x4fcc, 0x81, 0xb4, 0x1e, 0x39, 0x4c, 0xa2, 0x67, 0xeb);\r
+DEFINE_GUID(CLSID_TortoiseSVN_ADDED,0x3035134e, 0x7b7d, 0x4fcc, 0x81, 0xb4, 0x1e, 0x39, 0x4c, 0xa2, 0x67, 0xeb);\r
+DEFINE_GUID(CLSID_TortoiseSVN_IGNORED,0x3035134f, 0x7b7d, 0x4fcc, 0x81, 0xb4, 0x1e, 0x39, 0x4c, 0xa2, 0x67, 0xeb);\r
+DEFINE_GUID(CLSID_TortoiseSVN_UNVERSIONED,0x30351350, 0x7b7d, 0x4fcc, 0x81, 0xb4, 0x1e, 0x39, 0x4c, 0xa2, 0x67, 0xeb);\r
+\r
+\r
diff --git a/TortoiseShell/IconOverlay.cpp b/TortoiseShell/IconOverlay.cpp
new file mode 100644 (file)
index 0000000..5a2535f
--- /dev/null
@@ -0,0 +1,372 @@
+// TortoiseSVN - a Windows shell extension for easy version control\r
+\r
+// Copyright (C) 2003-2008 - TortoiseSVN\r
+\r
+// This program is free software; you can redistribute it and/or\r
+// modify it under the terms of the GNU General Public License\r
+// as published by the Free Software Foundation; either version 2\r
+// of the License, or (at your option) any later version.\r
+\r
+// This program is distributed in the hope that it will be useful,\r
+// but WITHOUT ANY WARRANTY; without even the implied warranty of\r
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\r
+// GNU General Public License for more details.\r
+\r
+// You should have received a copy of the GNU General Public License\r
+// along with this program; if not, write to the Free Software Foundation,\r
+// 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.\r
+//\r
+#include "stdafx.h"\r
+#include "ShellExt.h"\r
+#include "Guids.h"\r
+#include "PreserveChdir.h"\r
+#include "UnicodeUtils.h"\r
+#include "SVNStatus.h"\r
+#include "..\TSVNCache\CacheInterface.h"\r
+\r
+// "The Shell calls IShellIconOverlayIdentifier::GetOverlayInfo to request the\r
+//  location of the handler's icon overlay. The icon overlay handler returns\r
+//  the name of the file containing the overlay image, and its index within\r
+//  that file. The Shell then adds the icon overlay to the system image list."\r
+\r
+STDMETHODIMP CShellExt::GetOverlayInfo(LPWSTR /*pwszIconFile*/, int /*cchMax*/, int * /*pIndex*/, DWORD * /*pdwFlags*/)\r
+{\r
+       PreserveChdir preserveChdir;\r
+\r
+       // Now here's where we can find out if due to lack of enough overlay\r
+       // slots some of our overlays won't be shown.\r
+       // To do that we have to mark every overlay handler that's successfully\r
+       // loaded, so we can later check if some are missing\r
+       switch (m_State)\r
+       {\r
+               case FileStateVersioned                         : g_normalovlloaded = true; break;\r
+               case FileStateModified                          : g_modifiedovlloaded = true; break;\r
+               case FileStateConflict                          : g_conflictedovlloaded = true; break;\r
+               case FileStateDeleted                           : g_deletedovlloaded = true; break;\r
+               case FileStateReadOnly                          : g_readonlyovlloaded = true; break;\r
+               case FileStateLockedOverlay                     : g_lockedovlloaded = true; break;\r
+               case FileStateAddedOverlay                      : g_addedovlloaded = true; break;\r
+               case FileStateIgnoredOverlay            : g_ignoredovlloaded = true; break;\r
+               case FileStateUnversionedOverlay        : g_unversionedovlloaded = true; break;\r
+       }\r
+\r
+       // we don't have to set the icon file and/or the index here:\r
+       // the icons are handled by the TortoiseOverlays dll.\r
+    return S_OK;\r
+};\r
+\r
+STDMETHODIMP CShellExt::GetPriority(int *pPriority)\r
+{\r
+       switch (m_State)\r
+       {\r
+               case FileStateConflict:\r
+                       *pPriority = 0;\r
+                       break;\r
+               case FileStateModified:\r
+                       *pPriority = 1;\r
+                       break;\r
+               case FileStateDeleted:\r
+                       *pPriority = 2;\r
+                       break;\r
+               case FileStateReadOnly:\r
+                       *pPriority = 3;\r
+                       break;\r
+               case FileStateLockedOverlay:\r
+                       *pPriority = 4;\r
+                       break;\r
+               case FileStateAddedOverlay:\r
+                       *pPriority = 5;\r
+                       break;\r
+               case FileStateVersioned:\r
+                       *pPriority = 6;\r
+                       break;\r
+               default:\r
+                       *pPriority = 100;\r
+                       return S_FALSE;\r
+       }\r
+    return S_OK;\r
+}\r
+\r
+// "Before painting an object's icon, the Shell passes the object's name to\r
+//  each icon overlay handler's IShellIconOverlayIdentifier::IsMemberOf\r
+//  method. If a handler wants to have its icon overlay displayed,\r
+//  it returns S_OK. The Shell then calls the handler's\r
+//  IShellIconOverlayIdentifier::GetOverlayInfo method to determine which icon\r
+//  to display."\r
+\r
+STDMETHODIMP CShellExt::IsMemberOf(LPCWSTR pwszPath, DWORD /*dwAttrib*/)\r
+{\r
+       PreserveChdir preserveChdir;\r
+       svn_wc_status_kind status = svn_wc_status_none;\r
+       bool readonlyoverlay = false;\r
+       bool lockedoverlay = false;\r
+       if (pwszPath == NULL)\r
+               return S_FALSE;\r
+       const TCHAR* pPath = pwszPath;\r
+\r
+       // the shell sometimes asks overlays for invalid paths, e.g. for network\r
+       // printers (in that case the path is "0", at least for me here).\r
+       if (_tcslen(pPath)<2)\r
+               return S_FALSE;\r
+       // since the shell calls each and every overlay handler with the same filepath\r
+       // we use a small 'fast' cache of just one path here.\r
+       // To make sure that cache expires, clear it as soon as one handler is used.\r
+\r
+       AutoLocker lock(g_csGlobalCOMGuard);\r
+       if (_tcscmp(pPath, g_filepath.c_str())==0)\r
+       {\r
+               status = g_filestatus;\r
+               readonlyoverlay = g_readonlyoverlay;\r
+               lockedoverlay = g_lockedoverlay;\r
+       }\r
+       else\r
+       {\r
+               if (!g_ShellCache.IsPathAllowed(pPath))\r
+               {\r
+                       int drivenumber = -1;\r
+                       if ((m_State == FileStateVersioned) && g_ShellCache.ShowExcludedAsNormal() && \r
+                               ((drivenumber=PathGetDriveNumber(pPath))!=0)&&(drivenumber!=1) &&\r
+                               PathIsDirectory(pPath) && g_ShellCache.HasSVNAdminDir(pPath, true))\r
+                       {\r
+                               return S_OK;\r
+                       }\r
+                       return S_FALSE;\r
+               }\r
+\r
+               switch (g_ShellCache.GetCacheType())\r
+               {\r
+               case ShellCache::exe:\r
+                       {\r
+                               TSVNCacheResponse itemStatus;\r
+                               SecureZeroMemory(&itemStatus, sizeof(itemStatus));\r
+                               if (m_remoteCacheLink.GetStatusFromRemoteCache(CTSVNPath(pPath), &itemStatus, true))\r
+                               {\r
+                                       status = SVNStatus::GetMoreImportant(itemStatus.m_status.text_status, itemStatus.m_status.prop_status);\r
+                                       if ((itemStatus.m_kind == svn_node_file)&&(status == svn_wc_status_normal)&&((itemStatus.m_needslock && itemStatus.m_owner[0]==0)||(itemStatus.m_readonly)))\r
+                                               readonlyoverlay = true;\r
+                                       if (itemStatus.m_owner[0]!=0)\r
+                                               lockedoverlay = true;\r
+                               }\r
+                       }\r
+                       break;\r
+               case ShellCache::dll:\r
+                       {\r
+                               // Look in our caches for this item \r
+                               const FileStatusCacheEntry * s = m_CachedStatus.GetCachedItem(CTSVNPath(pPath));\r
+                               if (s)\r
+                               {\r
+                                       status = s->status;\r
+                               }\r
+                               else\r
+                               {\r
+                                       // No cached status available \r
+\r
+                                       // since the dwAttrib param of the IsMemberOf() function does not\r
+                                       // have the SFGAO_FOLDER flag set at all (it's 0 for files and folders!)\r
+                                       // we have to check if the path is a folder ourselves :(\r
+                                       if (PathIsDirectory(pPath))\r
+                                       {\r
+                                               if (g_ShellCache.HasSVNAdminDir(pPath, TRUE))\r
+                                               {\r
+                                                       if ((!g_ShellCache.IsRecursive()) && (!g_ShellCache.IsFolderOverlay()))\r
+                                                       {\r
+                                                               status = svn_wc_status_normal;\r
+                                                       }\r
+                                                       else\r
+                                                       {\r
+                                                               const FileStatusCacheEntry * s = m_CachedStatus.GetFullStatus(CTSVNPath(pPath), TRUE);\r
+                                                               status = s->status;\r
+                                                               status = SVNStatus::GetMoreImportant(svn_wc_status_normal, status);\r
+                                                       }\r
+                                               }\r
+                                               else\r
+                                               {\r
+                                                       status = svn_wc_status_none;\r
+                                               }\r
+                                       }\r
+                                       else\r
+                                       {\r
+                                               const FileStatusCacheEntry * s = m_CachedStatus.GetFullStatus(CTSVNPath(pPath), FALSE);\r
+                                               status = s->status;\r
+                                       }\r
+                               }\r
+                               if ((s)&&(status == svn_wc_status_normal)&&(s->needslock)&&(s->owner[0]==0))\r
+                                       readonlyoverlay = true;\r
+                               if ((s)&&(s->owner[0]!=0))\r
+                                       lockedoverlay = true;\r
+\r
+                       }\r
+                       break;\r
+               default:\r
+               case ShellCache::none:\r
+                       {\r
+                               // no cache means we only show a 'versioned' overlay on folders\r
+                               // with an admin directory\r
+                               if (PathIsDirectory(pPath))\r
+                               {\r
+                                       if (g_ShellCache.HasSVNAdminDir(pPath, TRUE))\r
+                                       {\r
+                                               status = svn_wc_status_normal;\r
+                                       }\r
+                                       else\r
+                                       {\r
+                                               status = svn_wc_status_none;\r
+                                       }\r
+                               }\r
+                               else\r
+                               {\r
+                                       status = svn_wc_status_none;\r
+                               }\r
+                       }\r
+                       break;\r
+               }\r
+               ATLTRACE(_T("Status %d for file %s\n"), status, pwszPath);\r
+       }\r
+       g_filepath.clear();\r
+       g_filepath = pPath;\r
+       g_filestatus = status;\r
+       g_readonlyoverlay = readonlyoverlay;\r
+       g_lockedoverlay = lockedoverlay;\r
+       \r
+       //the priority system of the shell doesn't seem to work as expected (or as I expected):\r
+       //as it seems that if one handler returns S_OK then that handler is used, no matter\r
+       //if other handlers would return S_OK too (they're never called on my machine!)\r
+       //So we return S_OK for ONLY ONE handler!\r
+       switch (status)\r
+       {\r
+               // note: we can show other overlays if due to lack of enough free overlay\r
+               // slots some of our overlays aren't loaded. But we assume that\r
+               // at least the 'normal' and 'modified' overlay are available.\r
+               case svn_wc_status_none:\r
+                       return S_FALSE;\r
+               case svn_wc_status_unversioned:\r
+                       if (g_ShellCache.ShowUnversionedOverlay() && g_unversionedovlloaded && (m_State == FileStateUnversionedOverlay))\r
+                       {\r
+                               g_filepath.clear();\r
+                               return S_OK;\r
+                       }\r
+                       return S_FALSE;\r
+               case svn_wc_status_ignored:\r
+                       if (g_ShellCache.ShowIgnoredOverlay() && g_ignoredovlloaded && (m_State == FileStateIgnoredOverlay))\r
+                       {\r
+                               g_filepath.clear();\r
+                               return S_OK;\r
+                       }\r
+                       return S_FALSE;\r
+               case svn_wc_status_normal:\r
+               case svn_wc_status_external:\r
+               case svn_wc_status_incomplete:\r
+                       if ((readonlyoverlay)&&(g_readonlyovlloaded))\r
+                       {\r
+                               if (m_State == FileStateReadOnly)\r
+                               {\r
+                                       g_filepath.clear();\r
+                                       return S_OK;\r
+                               }\r
+                               else\r
+                                       return S_FALSE;\r
+                       }\r
+                       else if ((lockedoverlay)&&(g_lockedovlloaded))\r
+                       {\r
+                               if (m_State == FileStateLockedOverlay)\r
+                               {\r
+                                       g_filepath.clear();\r
+                                       return S_OK;\r
+                               }\r
+                               else\r
+                                       return S_FALSE;\r
+                       }\r
+                       else if (m_State == FileStateVersioned)\r
+                       {\r
+                               g_filepath.clear();\r
+                               return S_OK;\r
+                       }\r
+                       else\r
+                               return S_FALSE;\r
+               case svn_wc_status_missing:\r
+               case svn_wc_status_deleted:\r
+                       if (g_deletedovlloaded)\r
+                       {\r
+                               if (m_State == FileStateDeleted)\r
+                               {\r
+                                       g_filepath.clear();\r
+                                       return S_OK;\r
+                               }\r
+                               else\r
+                                       return S_FALSE;\r
+                       }\r
+                       else\r
+                       {\r
+                               // the 'deleted' overlay isn't available (due to lack of enough\r
+                               // overlay slots). So just show the 'modified' overlay instead.\r
+                               if (m_State == FileStateModified)\r
+                               {\r
+                                       g_filepath.clear();\r
+                                       return S_OK;\r
+                               }\r
+                               else\r
+                                       return S_FALSE;\r
+                       }\r
+               case svn_wc_status_replaced:\r
+               case svn_wc_status_modified:\r
+               case svn_wc_status_merged:\r
+                       if (m_State == FileStateModified)\r
+                       {\r
+                               g_filepath.clear();\r
+                               return S_OK;\r
+                       }\r
+                       else\r
+                               return S_FALSE;\r
+               case svn_wc_status_added:\r
+                       if (g_addedovlloaded)\r
+                       {\r
+                               if (m_State== FileStateAddedOverlay)\r
+                               {\r
+                                       g_filepath.clear();\r
+                                       return S_OK;\r
+                               }\r
+                               else\r
+                                       return S_FALSE;\r
+                       }\r
+                       else\r
+                       {\r
+                               // the 'added' overlay isn't available (due to lack of enough\r
+                               // overlay slots). So just show the 'modified' overlay instead.\r
+                               if (m_State == FileStateModified)\r
+                               {\r
+                                       g_filepath.clear();\r
+                                       return S_OK;\r
+                               }\r
+                               else\r
+                                       return S_FALSE;\r
+                       }\r
+               case svn_wc_status_conflicted:\r
+               case svn_wc_status_obstructed:\r
+                       if (g_conflictedovlloaded)\r
+                       {\r
+                               if (m_State == FileStateConflict)\r
+                               {\r
+                                       g_filepath.clear();\r
+                                       return S_OK;\r
+                               }\r
+                               else\r
+                                       return S_FALSE;\r
+                       }\r
+                       else\r
+                       {\r
+                               // the 'conflicted' overlay isn't available (due to lack of enough\r
+                               // overlay slots). So just show the 'modified' overlay instead.\r
+                               if (m_State == FileStateModified)\r
+                               {\r
+                                       g_filepath.clear();\r
+                                       return S_OK;\r
+                               }\r
+                               else\r
+                                       return S_FALSE;\r
+                       }\r
+               default:\r
+                       return S_FALSE;\r
+       } // switch (status)\r
+    //return S_FALSE;\r
+}\r
+\r
diff --git a/TortoiseShell/ItemIDList.cpp b/TortoiseShell/ItemIDList.cpp
new file mode 100644 (file)
index 0000000..73c353a
--- /dev/null
@@ -0,0 +1,126 @@
+// TortoiseSVN - a Windows shell extension for easy version control\r
+\r
+// Copyright (C) 2003-2006 - Stefan Kueng\r
+\r
+// This program is free software; you can redistribute it and/or\r
+// modify it under the terms of the GNU General Public License\r
+// as published by the Free Software Foundation; either version 2\r
+// of the License, or (at your option) any later version.\r
+\r
+// This program is distributed in the hope that it will be useful,\r
+// but WITHOUT ANY WARRANTY; without even the implied warranty of\r
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\r
+// GNU General Public License for more details.\r
+\r
+// You should have received a copy of the GNU General Public License\r
+// along with this program; if not, write to the Free Software Foundation,\r
+// 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.\r
+//\r
+#include "StdAfx.h"\r
+#include "ShellExt.h"\r
+#include "ItemIDList.h"\r
+\r
+\r
+ItemIDList::ItemIDList(LPCITEMIDLIST item, LPCITEMIDLIST parent) :\r
+         item_ (item)\r
+       , parent_ (parent)\r
+       , count_ (-1)\r
+{\r
+}\r
+\r
+ItemIDList::~ItemIDList()\r
+{\r
+}\r
+\r
+int ItemIDList::size() const\r
+{\r
+       if (count_ == -1)\r
+       {\r
+               count_ = 0;\r
+               if (item_)\r
+               {\r
+                       LPCSHITEMID ptr = &item_->mkid;\r
+                       while (ptr != 0 && ptr->cb != 0)\r
+                       {\r
+                               ++count_;\r
+                               LPBYTE byte = (LPBYTE) ptr;\r
+                               byte += ptr->cb;\r
+                               ptr = (LPCSHITEMID) byte;\r
+                       }\r
+               }\r
+       }\r
+       return count_;\r
+}\r
+\r
+LPCSHITEMID ItemIDList::get(int index) const\r
+{\r
+       int count = 0;\r
+\r
+       if (item_ == NULL)\r
+               return NULL;\r
+       LPCSHITEMID ptr = &item_->mkid;\r
+       if (ptr == NULL)\r
+               return NULL;\r
+       while (ptr->cb != 0)\r
+       {\r
+               if (count == index)\r
+                       break;\r
+\r
+               ++count;\r
+               LPBYTE byte = (LPBYTE) ptr;\r
+               byte += ptr->cb;\r
+               ptr = (LPCSHITEMID) byte;\r
+       }\r
+       return ptr;\r
+\r
+}\r
+stdstring ItemIDList::toString()\r
+{\r
+       IShellFolder *shellFolder = NULL;\r
+       IShellFolder *parentFolder = NULL;\r
+       STRRET name;\r
+       TCHAR * szDisplayName = NULL;\r
+       stdstring ret;\r
+       HRESULT hr;\r
+\r
+       hr = ::SHGetDesktopFolder(&shellFolder);\r
+       if (!SUCCEEDED(hr))\r
+               return ret;\r
+       if (parent_)\r
+       {\r
+               hr = shellFolder->BindToObject(parent_, 0, IID_IShellFolder, (void**) &parentFolder);\r
+               if (!SUCCEEDED(hr))\r
+                       parentFolder = shellFolder;\r
+       } \r
+       else \r
+       {\r
+               parentFolder = shellFolder;\r
+       }\r
+\r
+       if ((parentFolder != 0)&&(item_ != 0))\r
+       {\r
+               hr = parentFolder->GetDisplayNameOf(item_, SHGDN_NORMAL | SHGDN_FORPARSING, &name);\r
+               if (!SUCCEEDED(hr))\r
+               {\r
+                       parentFolder->Release();\r
+                       return ret;\r
+               }\r
+               hr = StrRetToStr (&name, item_, &szDisplayName);\r
+               if (!SUCCEEDED(hr))\r
+                       return ret;\r
+       }\r
+       parentFolder->Release();\r
+       if (szDisplayName == NULL)\r
+       {\r
+               CoTaskMemFree(szDisplayName);\r
+               return ret;                     //to avoid a crash!\r
+       }\r
+       ret = szDisplayName;\r
+       CoTaskMemFree(szDisplayName);\r
+       return ret;\r
+}\r
+\r
+LPCITEMIDLIST ItemIDList::operator& ()\r
+{\r
+       return item_;\r
+}\r
diff --git a/TortoiseShell/ItemIDList.h b/TortoiseShell/ItemIDList.h
new file mode 100644 (file)
index 0000000..aa36d02
--- /dev/null
@@ -0,0 +1,42 @@
+// TortoiseSVN - a Windows shell extension for easy version control\r
+\r
+// Copyright (C) 2003-2006 - Stefan Kueng\r
+\r
+// This program is free software; you can redistribute it and/or\r
+// modify it under the terms of the GNU General Public License\r
+// as published by the Free Software Foundation; either version 2\r
+// of the License, or (at your option) any later version.\r
+\r
+// This program is distributed in the hope that it will be useful,\r
+// but WITHOUT ANY WARRANTY; without even the implied warranty of\r
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\r
+// GNU General Public License for more details.\r
+\r
+// You should have received a copy of the GNU General Public License\r
+// along with this program; if not, write to the Free Software Foundation,\r
+// 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.\r
+//\r
+#pragma once\r
+\r
+/**\r
+ * \ingroup TortoiseShell\r
+ * Represents a list of directory elements like folders and files.\r
+ */\r
+class ItemIDList  \r
+{\r
+public:\r
+       ItemIDList(LPCITEMIDLIST item, LPCITEMIDLIST parent = 0);\r
+\r
+       int size() const;\r
+       LPCSHITEMID get(int index) const;\r
+       virtual ~ItemIDList();\r
+\r
+       stdstring toString();\r
+\r
+       LPCITEMIDLIST operator& ();\r
+private:\r
+       LPCITEMIDLIST item_;\r
+       LPCITEMIDLIST parent_;\r
+       mutable int count_;\r
+};\r
+\r
diff --git a/TortoiseShell/PIDL.cpp b/TortoiseShell/PIDL.cpp
new file mode 100644 (file)
index 0000000..c8a6b0c
--- /dev/null
@@ -0,0 +1,30 @@
+// TortoiseSVN - a Windows shell extension for easy version control\r
+\r
+// Copyright (C) 2003-2006 - Stefan Kueng\r
+\r
+// This program is free software; you can redistribute it and/or\r
+// modify it under the terms of the GNU General Public License\r
+// as published by the Free Software Foundation; either version 2\r
+// of the License, or (at your option) any later version.\r
+\r
+// This program is distributed in the hope that it will be useful,\r
+// but WITHOUT ANY WARRANTY; without even the implied warranty of\r
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\r
+// GNU General Public License for more details.\r
+\r
+// You should have received a copy of the GNU General Public License\r
+// along with this program; if not, write to the Free Software Foundation,\r
+// 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.\r
+//\r
+#include "stdafx.h"\r
+#include "PIDL.h"\r
+\r
+PIDL::PIDL()\r
+{\r
+       ::SHGetMalloc(&malloc_);\r
+}\r
+\r
+PIDL::~PIDL()\r
+{\r
+       malloc_->Release();\r
+}\r
diff --git a/TortoiseShell/PIDL.h b/TortoiseShell/PIDL.h
new file mode 100644 (file)
index 0000000..76db4fa
--- /dev/null
@@ -0,0 +1,33 @@
+// TortoiseSVN - a Windows shell extension for easy version control\r
+\r
+// Copyright (C) 2003-2006 - Stefan Kueng\r
+\r
+// This program is free software; you can redistribute it and/or\r
+// modify it under the terms of the GNU General Public License\r
+// as published by the Free Software Foundation; either version 2\r
+// of the License, or (at your option) any later version.\r
+\r
+// This program is distributed in the hope that it will be useful,\r
+// but WITHOUT ANY WARRANTY; without even the implied warranty of\r
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\r
+// GNU General Public License for more details.\r
+\r
+// You should have received a copy of the GNU General Public License\r
+// along with this program; if not, write to the Free Software Foundation,\r
+// 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.\r
+//\r
+#pragma once\r
+\r
+/**\r
+ * \ingroup TortoiseShell\r
+ * Represents one entry of the class ItemIDList.\r
+ */\r
+class PIDL  \r
+{\r
+public:\r
+       PIDL();\r
+       virtual ~PIDL();\r
+private:\r
+       LPMALLOC malloc_;\r
+};\r
+\r
diff --git a/TortoiseShell/PreserveChdir.cpp b/TortoiseShell/PreserveChdir.cpp
new file mode 100644 (file)
index 0000000..4073f5e
--- /dev/null
@@ -0,0 +1,55 @@
+// TortoiseSVN - a Windows shell extension for easy version control\r
+\r
+// Copyright (C) 2003-2007 - TortoiseSVN\r
+\r
+// This program is free software; you can redistribute it and/or\r
+// modify it under the terms of the GNU General Public License\r
+// as published by the Free Software Foundation; either version 2\r
+// of the License, or (at your option) any later version.\r
+\r
+// This program is distributed in the hope that it will be useful,\r
+// but WITHOUT ANY WARRANTY; without even the implied warranty of\r
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\r
+// GNU General Public License for more details.\r
+\r
+// You should have received a copy of the GNU General Public License\r
+// along with this program; if not, write to the Free Software Foundation,\r
+// 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.\r
+//\r
+#include "stdafx.h"\r
+#include "PreserveChdir.h"\r
+\r
+PreserveChdir::PreserveChdir()\r
+{\r
+       DWORD len = GetCurrentDirectory(0, NULL);\r
+       if (len)\r
+       {\r
+               originalCurrentDirectory = new TCHAR[len];\r
+               if (GetCurrentDirectory(len, originalCurrentDirectory)==0)\r
+               {\r
+                       delete [] originalCurrentDirectory;\r
+                       originalCurrentDirectory = NULL;\r
+               }\r
+       }\r
+       else\r
+               originalCurrentDirectory = NULL;\r
+}\r
+\r
+PreserveChdir::~PreserveChdir()\r
+{\r
+       if (originalCurrentDirectory)\r
+       {\r
+               DWORD len = GetCurrentDirectory(0, NULL);\r
+               TCHAR * currentDirectory = new TCHAR[len];\r
+\r
+               // _tchdir is an expensive function - don't call it unless we really have to\r
+               GetCurrentDirectory(len, currentDirectory);\r
+               if(_tcscmp(currentDirectory, originalCurrentDirectory) != 0)\r
+               {\r
+                       SetCurrentDirectory(originalCurrentDirectory);\r
+               }\r
+               delete [] currentDirectory;\r
+               delete [] originalCurrentDirectory;\r
+               originalCurrentDirectory = NULL;\r
+       }\r
+}\r
diff --git a/TortoiseShell/PreserveChdir.h b/TortoiseShell/PreserveChdir.h
new file mode 100644 (file)
index 0000000..56f1a94
--- /dev/null
@@ -0,0 +1,40 @@
+// TortoiseSVN - a Windows shell extension for easy version control\r
+\r
+// Copyright (C) 2003-2006,2008 - Stefan Kueng\r
+\r
+// This program is free software; you can redistribute it and/or\r
+// modify it under the terms of the GNU General Public License\r
+// as published by the Free Software Foundation; either version 2\r
+// of the License, or (at your option) any later version.\r
+\r
+// This program is distributed in the hope that it will be useful,\r
+// but WITHOUT ANY WARRANTY; without even the implied warranty of\r
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\r
+// GNU General Public License for more details.\r
+\r
+// You should have received a copy of the GNU General Public License\r
+// along with this program; if not, write to the Free Software Foundation,\r
+// 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.\r
+//\r
+#pragma once\r
+\r
+/**\r
+ * \ingroup TortoiseShell\r
+ * Helper class to keep the current directory.\r
+ * When created, the current directory is saved and restored\r
+ * as soon as the object is destroyed.\r
+ * Since some of the SVN functions change the current directory\r
+ * which when in the explorer process space causes problems / crashes,\r
+ * this class is used to reset the current directory after calling\r
+ * those functions.\r
+ */\r
+class PreserveChdir\r
+{\r
+public:\r
+       PreserveChdir();\r
+       ~PreserveChdir();\r
+\r
+private:\r
+       TCHAR  * originalCurrentDirectory;\r
+};\r
+\r
diff --git a/TortoiseShell/RemoteCacheLink.cpp b/TortoiseShell/RemoteCacheLink.cpp
new file mode 100644 (file)
index 0000000..60318f7
--- /dev/null
@@ -0,0 +1,349 @@
+// TortoiseSVN - a Windows shell extension for easy version control\r
+\r
+// Copyright (C) 2003-2008 - TortoiseSVN\r
+\r
+// This program is free software; you can redistribute it and/or\r
+// modify it under the terms of the GNU General Public License\r
+// as published by the Free Software Foundation; either version 2\r
+// of the License, or (at your option) any later version.\r
+\r
+// This program is distributed in the hope that it will be useful,\r
+// but WITHOUT ANY WARRANTY; without even the implied warranty of\r
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\r
+// GNU General Public License for more details.\r
+\r
+// You should have received a copy of the GNU General Public License\r
+// along with this program; if not, write to the Free Software Foundation,\r
+// 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.\r
+//\r
+#include "StdAfx.h"\r
+#include "Remotecachelink.h"\r
+#include "ShellExt.h"\r
+#include "..\TSVNCache\CacheInterface.h"\r
+#include "TSVNPath.h"\r
+\r
+CRemoteCacheLink::CRemoteCacheLink(void) \r
+       : m_hPipe(INVALID_HANDLE_VALUE)\r
+       , m_hCommandPipe(INVALID_HANDLE_VALUE)\r
+{\r
+       SecureZeroMemory(&m_dummyStatus, sizeof(m_dummyStatus));\r
+       m_dummyStatus.text_status = svn_wc_status_none;\r
+       m_dummyStatus.prop_status = svn_wc_status_none;\r
+       m_dummyStatus.repos_text_status = svn_wc_status_none;\r
+       m_dummyStatus.repos_prop_status = svn_wc_status_none;\r
+       m_lastTimeout = 0;\r
+       m_critSec.Init();\r
+}\r
+\r
+CRemoteCacheLink::~CRemoteCacheLink(void)\r
+{\r
+       ClosePipe();\r
+       CloseCommandPipe();\r
+       m_critSec.Term();\r
+}\r
+\r
+bool CRemoteCacheLink::EnsurePipeOpen()\r
+{\r
+       AutoLocker lock(m_critSec);\r
+       if(m_hPipe != INVALID_HANDLE_VALUE)\r
+       {\r
+               return true;\r
+       }\r
+\r
+       m_hPipe = CreateFile(\r
+               GetCachePipeName(),                             // pipe name\r
+               GENERIC_READ |                                  // read and write access\r
+               GENERIC_WRITE,\r
+               0,                                                              // no sharing\r
+               NULL,                                                   // default security attributes\r
+               OPEN_EXISTING,                                  // opens existing pipe\r
+               FILE_FLAG_OVERLAPPED,                   // default attributes\r
+               NULL);                                                  // no template file\r
+\r
+       if (m_hPipe == INVALID_HANDLE_VALUE && GetLastError() == ERROR_PIPE_BUSY)\r
+       {\r
+               // TSVNCache is running but is busy connecting a different client.\r
+               // Do not give up immediately but wait for a few milliseconds until\r
+               // the server has created the next pipe instance\r
+               if (WaitNamedPipe(GetCachePipeName(), 50))\r
+               {\r
+                       m_hPipe = CreateFile(\r
+                               GetCachePipeName(),                             // pipe name\r
+                               GENERIC_READ |                                  // read and write access\r
+                               GENERIC_WRITE,\r
+                               0,                                                              // no sharing\r
+                               NULL,                                                   // default security attributes\r
+                               OPEN_EXISTING,                                  // opens existing pipe\r
+                               FILE_FLAG_OVERLAPPED,                   // default attributes\r
+                               NULL);                                                  // no template file\r
+               }\r
+       }\r
+\r
+\r
+       if (m_hPipe != INVALID_HANDLE_VALUE)\r
+       {\r
+               // The pipe connected; change to message-read mode.\r
+               DWORD dwMode;\r
+\r
+               dwMode = PIPE_READMODE_MESSAGE;\r
+               if(!SetNamedPipeHandleState(\r
+                       m_hPipe,    // pipe handle\r
+                       &dwMode,  // new pipe mode\r
+                       NULL,     // don't set maximum bytes\r
+                       NULL))    // don't set maximum time\r
+               {\r
+                       ATLTRACE("SetNamedPipeHandleState failed");\r
+                       CloseHandle(m_hPipe);\r
+                       m_hPipe = INVALID_HANDLE_VALUE;\r
+                       return false;\r
+               }\r
+               // create an unnamed (=local) manual reset event for use in the overlapped structure\r
+               m_hEvent = CreateEvent(NULL, TRUE, FALSE, NULL);\r
+               if (m_hEvent)\r
+                       return true;\r
+               ATLTRACE("CreateEvent failed");\r
+               ClosePipe();\r
+               return false;\r
+       }\r
+\r
+       return false;\r
+}\r
+\r
+bool CRemoteCacheLink::EnsureCommandPipeOpen()\r
+{\r
+       AutoLocker lock(m_critSec);\r
+       if(m_hCommandPipe != INVALID_HANDLE_VALUE)\r
+       {\r
+               return true;\r
+       }\r
+\r
+       m_hCommandPipe = CreateFile(\r
+               GetCacheCommandPipeName(),              // pipe name\r
+               GENERIC_READ |                                  // read and write access\r
+               GENERIC_WRITE,\r
+               0,                                                              // no sharing\r
+               NULL,                                                   // default security attributes\r
+               OPEN_EXISTING,                                  // opens existing pipe\r
+               FILE_FLAG_OVERLAPPED,                   // default attributes\r
+               NULL);                                                  // no template file\r
+\r
+       if (m_hCommandPipe == INVALID_HANDLE_VALUE && GetLastError() == ERROR_PIPE_BUSY)\r
+       {\r
+               // TSVNCache is running but is busy connecting a different client.\r
+               // Do not give up immediately but wait for a few milliseconds until\r
+               // the server has created the next pipe instance\r
+               if (WaitNamedPipe(GetCacheCommandPipeName(), 50))\r
+               {\r
+                       m_hCommandPipe = CreateFile(\r
+                               GetCacheCommandPipeName(),              // pipe name\r
+                               GENERIC_READ |                                  // read and write access\r
+                               GENERIC_WRITE,\r
+                               0,                                                              // no sharing\r
+                               NULL,                                                   // default security attributes\r
+                               OPEN_EXISTING,                                  // opens existing pipe\r
+                               FILE_FLAG_OVERLAPPED,                   // default attributes\r
+                               NULL);                                                  // no template file\r
+               }\r
+       }\r
+\r
+\r
+       if (m_hCommandPipe != INVALID_HANDLE_VALUE)\r
+       {\r
+               // The pipe connected; change to message-read mode.\r
+               DWORD dwMode;\r
+\r
+               dwMode = PIPE_READMODE_MESSAGE;\r
+               if(!SetNamedPipeHandleState(\r
+                       m_hCommandPipe,    // pipe handle\r
+                       &dwMode,  // new pipe mode\r
+                       NULL,     // don't set maximum bytes\r
+                       NULL))    // don't set maximum time\r
+               {\r
+                       ATLTRACE("SetNamedPipeHandleState failed");\r
+                       CloseHandle(m_hCommandPipe);\r
+                       m_hCommandPipe = INVALID_HANDLE_VALUE;\r
+                       return false;\r
+               }\r
+               return true;\r
+       }\r
+\r
+       return false;\r
+}\r
+\r
+void CRemoteCacheLink::ClosePipe()\r
+{\r
+       AutoLocker lock(m_critSec);\r
+\r
+       if(m_hPipe != INVALID_HANDLE_VALUE)\r
+       {\r
+               CloseHandle(m_hPipe);\r
+               CloseHandle(m_hEvent);\r
+               m_hPipe = INVALID_HANDLE_VALUE;\r
+               m_hEvent = INVALID_HANDLE_VALUE;\r
+       }\r
+}\r
+\r
+void CRemoteCacheLink::CloseCommandPipe()\r
+{\r
+       AutoLocker lock(m_critSec);\r
+\r
+       if(m_hCommandPipe != INVALID_HANDLE_VALUE)\r
+       {\r
+               // now tell the cache we don't need it's command thread anymore\r
+               DWORD cbWritten; \r
+               TSVNCacheCommand cmd;\r
+               SecureZeroMemory(&cmd, sizeof(TSVNCacheCommand));\r
+               cmd.command = TSVNCACHECOMMAND_END;\r
+               WriteFile( \r
+                       m_hCommandPipe,                 // handle to pipe \r
+                       &cmd,                   // buffer to write from \r
+                       sizeof(cmd),    // number of bytes to write \r
+                       &cbWritten,             // number of bytes written \r
+                       NULL);                  // not overlapped I/O \r
+               DisconnectNamedPipe(m_hCommandPipe); \r
+               CloseHandle(m_hCommandPipe); \r
+               m_hCommandPipe = INVALID_HANDLE_VALUE;\r
+       }\r
+}\r
+\r
+bool CRemoteCacheLink::GetStatusFromRemoteCache(const CTSVNPath& Path, TSVNCacheResponse* pReturnedStatus, bool bRecursive)\r
+{\r
+       if(!EnsurePipeOpen())\r
+       {\r
+               // We've failed to open the pipe - try and start the cache\r
+               // but only if the last try to start the cache was a certain time\r
+               // ago. If we just try over and over again without a small pause\r
+               // in between, the explorer is rendered unusable!\r
+               // Failing to start the cache can have different reasons: missing exe,\r
+               // missing registry key, corrupt exe, ...\r
+               if (((long)GetTickCount() - m_lastTimeout) < 0)\r
+                       return false;\r
+               STARTUPINFO startup;\r
+               PROCESS_INFORMATION process;\r
+               memset(&startup, 0, sizeof(startup));\r
+               startup.cb = sizeof(startup);\r
+               memset(&process, 0, sizeof(process));\r
+\r
+               CRegString cachePath(_T("Software\\TortoiseSVN\\CachePath"), _T("TSVNCache.exe"), false, HKEY_LOCAL_MACHINE);\r
+               CString sCachePath = cachePath;\r
+               if (CreateProcess(sCachePath.GetBuffer(sCachePath.GetLength()+1), _T(""), NULL, NULL, FALSE, 0, 0, 0, &startup, &process)==0)\r
+               {\r
+                       // It's not appropriate to do a message box here, because there may be hundreds of calls\r
+                       sCachePath.ReleaseBuffer();\r
+                       ATLTRACE("Failed to start cache\n");\r
+                       return false;\r
+               }\r
+               CloseHandle(process.hThread);\r
+               CloseHandle(process.hProcess);\r
+               sCachePath.ReleaseBuffer();\r
+\r
+               // Wait for the cache to open\r
+               long endTime = (long)GetTickCount()+1000;\r
+               while(!EnsurePipeOpen())\r
+               {\r
+                       if(((long)GetTickCount() - endTime) > 0)\r
+                       {\r
+                               m_lastTimeout = (long)GetTickCount()+10000;\r
+                               return false;\r
+                       }\r
+               }\r
+       }\r
+\r
+       AutoLocker lock(m_critSec);\r
+\r
+       DWORD nBytesRead;\r
+       TSVNCacheRequest request;\r
+       request.flags = TSVNCACHE_FLAGS_NONOTIFICATIONS;\r
+       if(bRecursive)\r
+       {\r
+               request.flags |= TSVNCACHE_FLAGS_RECUSIVE_STATUS;\r
+       }\r
+       wcsncpy_s(request.path, MAX_PATH+1, Path.GetWinPath(), MAX_PATH);\r
+       SecureZeroMemory(&m_Overlapped, sizeof(OVERLAPPED));\r
+       m_Overlapped.hEvent = m_hEvent;\r
+       // Do the transaction in overlapped mode.\r
+       // That way, if anything happens which might block this call\r
+       // we still can get out of it. We NEVER MUST BLOCK THE SHELL!\r
+       // A blocked shell is a very bad user impression, because users\r
+       // who don't know why it's blocked might find the only solution\r
+       // to such a problem is a reboot and therefore they might loose\r
+       // valuable data.\r
+       // One particular situation where the shell could hang is when\r
+       // the cache crashes and our crash report dialog comes up.\r
+       // Sure, it would be better to have no situations where the shell\r
+       // even can get blocked, but the timeout of 10 seconds is long enough\r
+       // so that users still recognize that something might be wrong and\r
+       // report back to us so we can investigate further.\r
+\r
+       BOOL fSuccess = TransactNamedPipe(m_hPipe,\r
+               &request, sizeof(request),\r
+               pReturnedStatus, sizeof(*pReturnedStatus),\r
+               &nBytesRead, &m_Overlapped);\r
+\r
+       if (!fSuccess)\r
+       {\r
+               if (GetLastError()!=ERROR_IO_PENDING)\r
+               {\r
+                       //OutputDebugStringA("TortoiseShell: TransactNamedPipe failed\n");\r
+                       ClosePipe();\r
+                       return false;\r
+               }\r
+\r
+               // TransactNamedPipe is working in an overlapped operation.\r
+               // Wait for it to finish\r
+               DWORD dwWait = WaitForSingleObject(m_hEvent, 10000);\r
+               if (dwWait == WAIT_OBJECT_0)\r
+               {\r
+                       fSuccess = GetOverlappedResult(m_hPipe, &m_Overlapped, &nBytesRead, FALSE);\r
+               }\r
+               else\r
+               {\r
+                       // the cache didn't respond!\r
+                       fSuccess = FALSE;\r
+               }\r
+       }\r
+\r
+       if (fSuccess)\r
+       {\r
+               if(nBytesRead == sizeof(TSVNCacheResponse))\r
+               {\r
+                       // This is a full response - we need to fix-up some pointers\r
+                       pReturnedStatus->m_status.entry = &pReturnedStatus->m_entry;\r
+                       pReturnedStatus->m_entry.url = pReturnedStatus->m_url;\r
+               }\r
+               else\r
+               {\r
+                       pReturnedStatus->m_status.entry = NULL;\r
+               }\r
+\r
+               return true;\r
+       }\r
+       ClosePipe();\r
+       return false;\r
+}\r
+\r
+bool CRemoteCacheLink::ReleaseLockForPath(const CTSVNPath& path)\r
+{\r
+       EnsureCommandPipeOpen();\r
+       if (m_hCommandPipe != INVALID_HANDLE_VALUE) \r
+       {\r
+               DWORD cbWritten; \r
+               TSVNCacheCommand cmd;\r
+               SecureZeroMemory(&cmd, sizeof(TSVNCacheCommand));\r
+               cmd.command = TSVNCACHECOMMAND_RELEASE;\r
+               wcsncpy_s(cmd.path, MAX_PATH+1, path.GetDirectory().GetWinPath(), MAX_PATH);\r
+               BOOL fSuccess = WriteFile( \r
+                       m_hCommandPipe, // handle to pipe \r
+                       &cmd,                   // buffer to write from \r
+                       sizeof(cmd),    // number of bytes to write \r
+                       &cbWritten,             // number of bytes written \r
+                       NULL);                  // not overlapped I/O \r
+               if (! fSuccess || sizeof(cmd) != cbWritten)\r
+               {\r
+                       CloseCommandPipe();\r
+                       return false;\r
+               }\r
+               return true;\r
+       }\r
+       return false;\r
+}\r
diff --git a/TortoiseShell/RemoteCacheLink.h b/TortoiseShell/RemoteCacheLink.h
new file mode 100644 (file)
index 0000000..674d209
--- /dev/null
@@ -0,0 +1,57 @@
+// TortoiseSVN - a Windows shell extension for easy version control\r
+\r
+// Copyright (C) 2003-2008 - TortoiseSVN\r
+\r
+// This program is free software; you can redistribute it and/or\r
+// modify it under the terms of the GNU General Public License\r
+// as published by the Free Software Foundation; either version 2\r
+// of the License, or (at your option) any later version.\r
+\r
+// This program is distributed in the hope that it will be useful,\r
+// but WITHOUT ANY WARRANTY; without even the implied warranty of\r
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\r
+// GNU General Public License for more details.\r
+\r
+// You should have received a copy of the GNU General Public License\r
+// along with this program; if not, write to the Free Software Foundation,\r
+// 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.\r
+//\r
+#pragma once\r
+\r
+struct TSVNCacheResponse;\r
+class CTSVNPath;\r
+\r
+/**\r
+ * \ingroup TortoiseShell\r
+ * This class provides the link to the cache process.\r
+ */\r
+class CRemoteCacheLink\r
+{\r
+public:\r
+       CRemoteCacheLink(void);\r
+       ~CRemoteCacheLink(void);\r
+\r
+public:\r
+       bool GetStatusFromRemoteCache(const CTSVNPath& Path, TSVNCacheResponse* pReturnedStatus, bool bRecursive);\r
+       bool ReleaseLockForPath(const CTSVNPath& path);\r
+\r
+private:\r
+       bool EnsurePipeOpen();\r
+       void ClosePipe();\r
+\r
+       bool EnsureCommandPipeOpen();\r
+       void CloseCommandPipe();\r
+\r
+private:\r
+       HANDLE m_hPipe;\r
+       OVERLAPPED m_Overlapped;\r
+       HANDLE m_hEvent;\r
+\r
+       HANDLE m_hCommandPipe;\r
+\r
+\r
+       CComCriticalSection m_critSec;\r
+       svn_wc_status2_t m_dummyStatus;\r
+       long m_lastTimeout;\r
+\r
+};\r
diff --git a/TortoiseShell/SVNPropertyPage.cpp b/TortoiseShell/SVNPropertyPage.cpp
new file mode 100644 (file)
index 0000000..b29e9c0
--- /dev/null
@@ -0,0 +1,422 @@
+// TortoiseSVN - a Windows shell extension for easy version control\r
+\r
+// Copyright (C) 2003-2008 - TortoiseSVN\r
+\r
+// This program is free software; you can redistribute it and/or\r
+// modify it under the terms of the GNU General Public License\r
+// as published by the Free Software Foundation; either version 2\r
+// of the License, or (at your option) any later version.\r
+\r
+// This program is distributed in the hope that it will be useful,\r
+// but WITHOUT ANY WARRANTY; without even the implied warranty of\r
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\r
+// GNU General Public License for more details.\r
+\r
+// You should have received a copy of the GNU General Public License\r
+// along with this program; if not, write to the Free Software Foundation,\r
+// 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.\r
+//\r
+#include "stdafx.h"\r
+\r
+#include "ShellExt.h"\r
+#include "svnpropertypage.h"\r
+#include "UnicodeUtils.h"\r
+#include "PathUtils.h"\r
+#include "SVNStatus.h"\r
+\r
+#define MAX_STRING_LENGTH              4096                    //should be big enough\r
+\r
+// Nonmember function prototypes\r
+BOOL CALLBACK PageProc (HWND, UINT, WPARAM, LPARAM);\r
+UINT CALLBACK PropPageCallbackProc ( HWND hwnd, UINT uMsg, LPPROPSHEETPAGE ppsp );\r
+\r
+// CShellExt member functions (needed for IShellPropSheetExt)\r
+STDMETHODIMP CShellExt::AddPages (LPFNADDPROPSHEETPAGE lpfnAddPage,\r
+                                  LPARAM lParam)\r
+{\r
+       for (std::vector<stdstring>::iterator I = files_.begin(); I != files_.end(); ++I)\r
+       {\r
+               SVNStatus svn = SVNStatus();\r
+               if (svn.GetStatus(CTSVNPath(I->c_str())) == (-2))\r
+                       return NOERROR;                 // file/directory not under version control\r
+\r
+               if (svn.status->entry == NULL)\r
+                       return NOERROR;\r
+       }\r
+\r
+       if (files_.size() == 0)\r
+               return NOERROR;\r
+\r
+       LoadLangDll();\r
+    PROPSHEETPAGE psp;\r
+       SecureZeroMemory(&psp, sizeof(PROPSHEETPAGE));\r
+       HPROPSHEETPAGE hPage;\r
+       CSVNPropertyPage *sheetpage = new CSVNPropertyPage(files_);\r
+\r
+    psp.dwSize = sizeof (psp);\r
+    psp.dwFlags = PSP_USEREFPARENT | PSP_USETITLE | PSP_USEICONID | PSP_USECALLBACK;   \r
+       psp.hInstance = g_hResInst;\r
+       psp.pszTemplate = MAKEINTRESOURCE(IDD_PROPPAGE);\r
+    psp.pszIcon = MAKEINTRESOURCE(IDI_APPSMALL);\r
+    psp.pszTitle = _T("Subversion");\r
+    psp.pfnDlgProc = (DLGPROC) PageProc;\r
+    psp.lParam = (LPARAM) sheetpage;\r
+    psp.pfnCallback = PropPageCallbackProc;\r
+    psp.pcRefParent = &g_cRefThisDll;\r
+\r
+    hPage = CreatePropertySheetPage (&psp);\r
+\r
+       if (hPage != NULL)\r
+       {\r
+        if (!lpfnAddPage (hPage, lParam))\r
+        {\r
+            delete sheetpage;\r
+            DestroyPropertySheetPage (hPage);\r
+        }\r
+       }\r
+\r
+    return NOERROR;\r
+}\r
+\r
+\r
+\r
+STDMETHODIMP CShellExt::ReplacePage (UINT /*uPageID*/, LPFNADDPROPSHEETPAGE /*lpfnReplaceWith*/, LPARAM /*lParam*/)\r
+{\r
+    return E_FAIL;\r
+}\r
+\r
+/////////////////////////////////////////////////////////////////////////////\r
+// Dialog procedures and other callback functions\r
+\r
+BOOL CALLBACK PageProc (HWND hwnd, UINT uMessage, WPARAM wParam, LPARAM lParam)\r
+{\r
+    CSVNPropertyPage * sheetpage;\r
+\r
+    if (uMessage == WM_INITDIALOG)\r
+    {\r
+        sheetpage = (CSVNPropertyPage*) ((LPPROPSHEETPAGE) lParam)->lParam;\r
+        SetWindowLongPtr (hwnd, GWLP_USERDATA, (LONG_PTR) sheetpage);\r
+        sheetpage->SetHwnd(hwnd);\r
+    }\r
+    else\r
+    {\r
+        sheetpage = (CSVNPropertyPage*) GetWindowLongPtr (hwnd, GWLP_USERDATA);\r
+    }\r
+\r
+    if (sheetpage != 0L)\r
+        return sheetpage->PageProc(hwnd, uMessage, wParam, lParam);\r
+    else\r
+        return FALSE;\r
+}\r
+\r
+UINT CALLBACK PropPageCallbackProc ( HWND /*hwnd*/, UINT uMsg, LPPROPSHEETPAGE ppsp )\r
+{\r
+    // Delete the page before closing.\r
+    if (PSPCB_RELEASE == uMsg)\r
+    {\r
+        CSVNPropertyPage* sheetpage = (CSVNPropertyPage*) ppsp->lParam;\r
+        if (sheetpage != NULL)\r
+            delete sheetpage;\r
+    }\r
+    return 1;\r
+}\r
+\r
+// *********************** CSVNPropertyPage *************************\r
+\r
+CSVNPropertyPage::CSVNPropertyPage(const std::vector<stdstring> &newFilenames)\r
+       :filenames(newFilenames)\r
+{\r
+}\r
+\r
+CSVNPropertyPage::~CSVNPropertyPage(void)\r
+{\r
+}\r
+\r
+void CSVNPropertyPage::SetHwnd(HWND newHwnd)\r
+{\r
+    m_hwnd = newHwnd;\r
+}\r
+\r
+BOOL CSVNPropertyPage::PageProc (HWND /*hwnd*/, UINT uMessage, WPARAM wParam, LPARAM lParam)\r
+{\r
+       switch (uMessage)\r
+       {\r
+       case WM_INITDIALOG:\r
+               {\r
+                       InitWorkfileView();\r
+                       return TRUE;\r
+               }\r
+       case WM_NOTIFY:\r
+               {\r
+                       LPNMHDR point = (LPNMHDR)lParam;\r
+                       int code = point->code;\r
+                       //\r
+                       // Respond to notifications.\r
+                       //    \r
+                       if (code == PSN_APPLY)\r
+                       {\r
+                       }\r
+                       SetWindowLongPtr (m_hwnd, DWLP_MSGRESULT, FALSE);\r
+                       return TRUE;        \r
+\r
+                       }\r
+               case WM_DESTROY:\r
+                       return TRUE;\r
+\r
+               case WM_COMMAND:\r
+                       switch (HIWORD(wParam))\r
+                       {\r
+                               case BN_CLICKED:\r
+                                       if (LOWORD(wParam) == IDC_SHOWLOG)\r
+                                       {\r
+                                               STARTUPINFO startup;\r
+                                               PROCESS_INFORMATION process;\r
+                                               memset(&startup, 0, sizeof(startup));\r
+                                               startup.cb = sizeof(startup);\r
+                                               memset(&process, 0, sizeof(process));\r
+                                               CRegStdString tortoiseProcPath(_T("Software\\TortoiseSVN\\ProcPath"), _T("TortoiseProc.exe"), false, HKEY_LOCAL_MACHINE);\r
+                                               stdstring svnCmd = _T(" /command:");\r
+                                               svnCmd += _T("log /path:\"");\r
+                                               svnCmd += filenames.front().c_str();\r
+                                               svnCmd += _T("\"");\r
+                                               if (CreateProcess(((stdstring)tortoiseProcPath).c_str(), const_cast<TCHAR*>(svnCmd.c_str()), NULL, NULL, FALSE, 0, 0, 0, &startup, &process))\r
+                                               {\r
+                                                       CloseHandle(process.hThread);\r
+                                                       CloseHandle(process.hProcess);\r
+                                               }\r
+                                       }\r
+                                       if (LOWORD(wParam) == IDC_EDITPROPERTIES)\r
+                                       {\r
+                                               DWORD pathlength = GetTempPath(0, NULL);\r
+                                               TCHAR * path = new TCHAR[pathlength+1];\r
+                                               TCHAR * tempFile = new TCHAR[pathlength + 100];\r
+                                               GetTempPath (pathlength+1, path);\r
+                                               GetTempFileName (path, _T("svn"), 0, tempFile);\r
+                                               stdstring retFilePath = stdstring(tempFile);\r
+\r
+                                               HANDLE file = ::CreateFile (tempFile,\r
+                                                       GENERIC_WRITE, \r
+                                                       FILE_SHARE_READ, \r
+                                                       0, \r
+                                                       CREATE_ALWAYS, \r
+                                                       FILE_ATTRIBUTE_TEMPORARY,\r
+                                                       0);\r
+\r
+                                               delete [] path;\r
+                                               delete [] tempFile;\r
+                                               if (file != INVALID_HANDLE_VALUE)\r
+                                               {\r
+                                                       DWORD written = 0;\r
+                                                       for (std::vector<stdstring>::iterator I = filenames.begin(); I != filenames.end(); ++I)\r
+                                                       {\r
+                                                               ::WriteFile (file, I->c_str(), I->size()*sizeof(TCHAR), &written, 0);\r
+                                                               ::WriteFile (file, _T("\n"), 2, &written, 0);\r
+                                                       }\r
+                                                       ::CloseHandle(file);\r
+\r
+                                                       STARTUPINFO startup;\r
+                                                       PROCESS_INFORMATION process;\r
+                                                       memset(&startup, 0, sizeof(startup));\r
+                                                       startup.cb = sizeof(startup);\r
+                                                       memset(&process, 0, sizeof(process));\r
+                                                       CRegStdString tortoiseProcPath(_T("Software\\TortoiseSVN\\ProcPath"), _T("TortoiseProc.exe"), false, HKEY_LOCAL_MACHINE);\r
+                                                       stdstring svnCmd = _T(" /command:");\r
+                                                       svnCmd += _T("properties /pathfile:\"");\r
+                                                       svnCmd += retFilePath.c_str();\r
+                                                       svnCmd += _T("\"");\r
+                                                       svnCmd += _T(" /deletepathfile");\r
+                                                       if (CreateProcess(((stdstring)tortoiseProcPath).c_str(), const_cast<TCHAR*>(svnCmd.c_str()), NULL, NULL, FALSE, 0, 0, 0, &startup, &process))\r
+                                                       {\r
+                                                               CloseHandle(process.hThread);\r
+                                                               CloseHandle(process.hProcess);\r
+                                                       }\r
+                                               }\r
+                                       }\r
+                                       break;\r
+                       } // switch (HIWORD(wParam)) \r
+       } // switch (uMessage) \r
+       return FALSE;\r
+}\r
+void CSVNPropertyPage::Time64ToTimeString(__time64_t time, TCHAR * buf, size_t buflen)\r
+{\r
+       struct tm newtime;\r
+       SYSTEMTIME systime;\r
+       TCHAR timebuf[MAX_STRING_LENGTH];\r
+       TCHAR datebuf[MAX_STRING_LENGTH];\r
+\r
+       LCID locale = (WORD)CRegStdWORD(_T("Software\\TortoiseSVN\\LanguageID"), MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT));\r
+       locale = MAKELCID(locale, SORT_DEFAULT);\r
+\r
+       *buf = '\0';\r
+       if (time)\r
+       {\r
+               _localtime64_s(&newtime, &time);\r
+\r
+               systime.wDay = (WORD)newtime.tm_mday;\r
+               systime.wDayOfWeek = (WORD)newtime.tm_wday;\r
+               systime.wHour = (WORD)newtime.tm_hour;\r
+               systime.wMilliseconds = 0;\r
+               systime.wMinute = (WORD)newtime.tm_min;\r
+               systime.wMonth = (WORD)newtime.tm_mon+1;\r
+               systime.wSecond = (WORD)newtime.tm_sec;\r
+               systime.wYear = (WORD)newtime.tm_year+1900;\r
+               if (CRegStdWORD(_T("Software\\TortoiseSVN\\LogDateFormat")) == 1)\r
+                       GetDateFormat(locale, DATE_SHORTDATE, &systime, NULL, datebuf, MAX_STRING_LENGTH);\r
+               else\r
+                       GetDateFormat(locale, DATE_LONGDATE, &systime, NULL, datebuf, MAX_STRING_LENGTH);\r
+               GetTimeFormat(locale, 0, &systime, NULL, timebuf, MAX_STRING_LENGTH);\r
+               *buf = '\0';\r
+               _tcsncat_s(buf, buflen, timebuf, MAX_STRING_LENGTH-1);\r
+               _tcsncat_s(buf, buflen, _T(", "), MAX_STRING_LENGTH-1);\r
+               _tcsncat_s(buf, buflen, datebuf, MAX_STRING_LENGTH-1);\r
+       }\r
+}\r
+\r
+void CSVNPropertyPage::InitWorkfileView()\r
+{\r
+       SVNStatus svn = SVNStatus();\r
+       TCHAR tbuf[MAX_STRING_LENGTH];\r
+       if (filenames.size() == 1)\r
+       {\r
+               if (svn.GetStatus(CTSVNPath(filenames.front().c_str()))>(-2))\r
+               {\r
+                       TCHAR buf[MAX_STRING_LENGTH];\r
+                       __time64_t      time;\r
+                       if (svn.status->entry != NULL)\r
+                       {\r
+                               LoadLangDll();\r
+                               if (svn.status->text_status == svn_wc_status_added)\r
+                               {\r
+                                       // disable the "show log" button for added files\r
+                                       HWND showloghwnd = GetDlgItem(m_hwnd, IDC_SHOWLOG);\r
+                                       if (GetFocus() == showloghwnd)\r
+                                               ::SendMessage(m_hwnd, WM_NEXTDLGCTL, 0, FALSE);\r
+                                       ::EnableWindow(showloghwnd, FALSE);\r
+                               }\r
+                               else\r
+                               {\r
+                                       _stprintf_s(buf, MAX_STRING_LENGTH, _T("%d"), svn.status->entry->revision);\r
+                                       SetDlgItemText(m_hwnd, IDC_REVISION, buf);\r
+                               }\r
+                               if (svn.status->entry->url)\r
+                               {\r
+                                       size_t len = strlen(svn.status->entry->url);\r
+                                       char * unescapedurl = new char[len+1];\r
+                                       strcpy_s(unescapedurl, len+1, svn.status->entry->url);\r
+                                       CPathUtils::Unescape(unescapedurl);\r
+                                       SetDlgItemText(m_hwnd, IDC_REPOURL, UTF8ToWide(unescapedurl).c_str());\r
+                                       if (strcmp(unescapedurl, svn.status->entry->url))\r
+                                       {\r
+                                               ShowWindow(GetDlgItem(m_hwnd, IDC_ESCAPEDURLLABEL), SW_SHOW);\r
+                                               ShowWindow(GetDlgItem(m_hwnd, IDC_REPOURLUNESCAPED), SW_SHOW);\r
+                                               SetDlgItemText(m_hwnd, IDC_REPOURLUNESCAPED, UTF8ToWide(svn.status->entry->url).c_str());\r
+                                       }\r
+                                       else\r
+                                       {\r
+                                               ShowWindow(GetDlgItem(m_hwnd, IDC_ESCAPEDURLLABEL), SW_HIDE);\r
+                                               ShowWindow(GetDlgItem(m_hwnd, IDC_REPOURLUNESCAPED), SW_HIDE);\r
+                                       }\r
+                                       delete [] unescapedurl;\r
+                               }\r
+                               else\r
+                               {\r
+                                       ShowWindow(GetDlgItem(m_hwnd, IDC_ESCAPEDURLLABEL), SW_HIDE);\r
+                                       ShowWindow(GetDlgItem(m_hwnd, IDC_REPOURLUNESCAPED), SW_HIDE);\r
+                               }\r
+                               if (svn.status->text_status != svn_wc_status_added)\r
+                               {\r
+                                       _stprintf_s(buf, MAX_STRING_LENGTH, _T("%d"), svn.status->entry->cmt_rev);\r
+                                       SetDlgItemText(m_hwnd, IDC_CREVISION, buf);\r
+                                       time = (__time64_t)svn.status->entry->cmt_date/1000000L;\r
+                                       Time64ToTimeString(time, buf, MAX_STRING_LENGTH);\r
+                                       SetDlgItemText(m_hwnd, IDC_CDATE, buf);\r
+                               }\r
+                               if (svn.status->entry->cmt_author)\r
+                                       SetDlgItemText(m_hwnd, IDC_AUTHOR, UTF8ToWide(svn.status->entry->cmt_author).c_str());\r
+                               SVNStatus::GetStatusString(g_hResInst, svn.status->text_status, buf, sizeof(buf)/sizeof(TCHAR), (WORD)CRegStdWORD(_T("Software\\TortoiseSVN\\LanguageID"), MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT)));\r
+                               SetDlgItemText(m_hwnd, IDC_TEXTSTATUS, buf);\r
+                               SVNStatus::GetStatusString(g_hResInst, svn.status->prop_status, buf, sizeof(buf)/sizeof(TCHAR), (WORD)CRegStdWORD(_T("Software\\TortoiseSVN\\LanguageID"), MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT)));\r
+                               SetDlgItemText(m_hwnd, IDC_PROPSTATUS, buf);\r
+                               time = (__time64_t)svn.status->entry->text_time/1000000L;\r
+                               Time64ToTimeString(time, buf, MAX_STRING_LENGTH);\r
+                               SetDlgItemText(m_hwnd, IDC_TEXTDATE, buf);\r
+                               time = (__time64_t)svn.status->entry->prop_time/1000000L;\r
+                               Time64ToTimeString(time, buf, MAX_STRING_LENGTH);\r
+                               SetDlgItemText(m_hwnd, IDC_PROPDATE, buf);\r
+\r
+                               if (svn.status->entry->lock_owner)\r
+                                       SetDlgItemText(m_hwnd, IDC_LOCKOWNER, UTF8ToWide(svn.status->entry->lock_owner).c_str());\r
+                               time = (__time64_t)svn.status->entry->lock_creation_date/1000000L;\r
+                               Time64ToTimeString(time, buf, MAX_STRING_LENGTH);\r
+                               SetDlgItemText(m_hwnd, IDC_LOCKDATE, buf);\r
+       \r
+                               if (svn.status->entry->uuid)\r
+                                       SetDlgItemText(m_hwnd, IDC_REPOUUID, UTF8ToWide(svn.status->entry->uuid).c_str());\r
+                               if (svn.status->entry->changelist)\r
+                                       SetDlgItemText(m_hwnd, IDC_CHANGELIST, UTF8ToWide(svn.status->entry->changelist).c_str());\r
+                               SVNStatus::GetDepthString(g_hResInst, svn.status->entry->depth, buf, sizeof(buf)/sizeof(TCHAR), (WORD)CRegStdWORD(_T("Software\\TortoiseSVN\\LanguageID"), MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT)));\r
+                               SetDlgItemText(m_hwnd, IDC_DEPTHEDIT, buf);\r
+\r
+                               if (svn.status->entry->checksum)\r
+                                       SetDlgItemText(m_hwnd, IDC_CHECKSUM, UTF8ToWide(svn.status->entry->checksum).c_str());\r
+\r
+                               if (svn.status->locked)\r
+                                       MAKESTRING(IDS_YES);\r
+                               else\r
+                                       MAKESTRING(IDS_NO);\r
+                               SetDlgItemText(m_hwnd, IDC_LOCKED, stringtablebuffer);\r
+\r
+                               if (svn.status->copied)\r
+                                       MAKESTRING(IDS_YES);\r
+                               else\r
+                                       MAKESTRING(IDS_NO);\r
+                               SetDlgItemText(m_hwnd, IDC_COPIED, stringtablebuffer);\r
+\r
+                               if (svn.status->switched)\r
+                                       MAKESTRING(IDS_YES);\r
+                               else\r
+                                       MAKESTRING(IDS_NO);\r
+                               SetDlgItemText(m_hwnd, IDC_SWITCHED, stringtablebuffer);\r
+                       } // if (svn.status->entry != NULL)\r
+               } // if (svn.GetStatus(CTSVNPath(filenames.front().c_str()))>(-2))\r
+       } // if (filenames.size() == 1) \r
+       else if (filenames.size() != 0)\r
+       {\r
+               //deactivate the show log button\r
+               HWND logwnd = GetDlgItem(m_hwnd, IDC_SHOWLOG);\r
+               if (GetFocus() == logwnd)\r
+                       ::SendMessage(m_hwnd, WM_NEXTDLGCTL, 0, FALSE);\r
+               ::EnableWindow(logwnd, FALSE);\r
+               //get the handle of the list view\r
+               if (svn.GetStatus(CTSVNPath(filenames.front().c_str()))>(-2))\r
+               {\r
+                       if (svn.status->entry != NULL)\r
+                       {\r
+                               LoadLangDll();\r
+                               if (svn.status->entry->url)\r
+                               {\r
+                                       CPathUtils::Unescape((char*)svn.status->entry->url);\r
+                                       _tcsncpy_s(tbuf, MAX_STRING_LENGTH, UTF8ToWide(svn.status->entry->url).c_str(), 4095);\r
+                                       TCHAR * ptr = _tcsrchr(tbuf, '/');\r
+                                       if (ptr != 0)\r
+                                       {\r
+                                               *ptr = 0;\r
+                                       }\r
+                                       SetDlgItemText(m_hwnd, IDC_REPOURL, tbuf);\r
+                               }\r
+                               SetDlgItemText(m_hwnd, IDC_LOCKED, _T(""));\r
+                               SetDlgItemText(m_hwnd, IDC_COPIED, _T(""));\r
+                               SetDlgItemText(m_hwnd, IDC_SWITCHED, _T(""));\r
+\r
+                               SetDlgItemText(m_hwnd, IDC_DEPTHEDIT, _T(""));\r
+                               SetDlgItemText(m_hwnd, IDC_CHECKSUM, _T(""));\r
+                               SetDlgItemText(m_hwnd, IDC_REPOUUID, _T(""));\r
+\r
+                               ShowWindow(GetDlgItem(m_hwnd, IDC_ESCAPEDURLLABEL), SW_HIDE);\r
+                               ShowWindow(GetDlgItem(m_hwnd, IDC_REPOURLUNESCAPED), SW_HIDE);\r
+                       }\r
+               }\r
+       } \r
+}\r
+\r
+\r
diff --git a/TortoiseShell/SVNPropertyPage.h b/TortoiseShell/SVNPropertyPage.h
new file mode 100644 (file)
index 0000000..ef64017
--- /dev/null
@@ -0,0 +1,94 @@
+// TortoiseSVN - a Windows shell extension for easy version control\r
+\r
+// Copyright (C) 2003-2006 - Stefan Kueng\r
+\r
+// This program is free software; you can redistribute it and/or\r
+// modify it under the terms of the GNU General Public License\r
+// as published by the Free Software Foundation; either version 2\r
+// of the License, or (at your option) any later version.\r
+\r
+// This program is distributed in the hope that it will be useful,\r
+// but WITHOUT ANY WARRANTY; without even the implied warranty of\r
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\r
+// GNU General Public License for more details.\r
+\r
+// You should have received a copy of the GNU General Public License\r
+// along with this program; if not, write to the Free Software Foundation,\r
+// 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.\r
+//\r
+#pragma once\r
+#include "ShellUpdater.h"\r
+\r
+#define ListView_GetItemTextEx(hwndLV, i, iSubItem_, __buf) \\r
+{ \\r
+  int nLen = 1024;\\r
+  int nRes;\\r
+  LV_ITEM _ms_lvi;\\r
+  _ms_lvi.iSubItem = iSubItem_;\\r
+  do\\r
+  {\\r
+       nLen += 2;\\r
+       _ms_lvi.cchTextMax = nLen;\\r
+    if (__buf)\\r
+               delete[] __buf;\\r
+       __buf = new TCHAR[nLen];\\r
+       _ms_lvi.pszText = __buf;\\r
+    nRes  = (int)::SendMessage((hwndLV), LVM_GETITEMTEXT, (WPARAM)(i), (LPARAM)(LV_ITEM *)&_ms_lvi);\\r
+  } while (nRes == nLen-1);\\r
+}\r
+#define GetDlgItemTextEx(hwndDlg, _id, __buf) \\r
+{\\r
+       int nLen = 1024;\\r
+       int nRes;\\r
+       do\\r
+       {\\r
+               nLen *= 2;\\r
+               if (__buf)\\r
+                       delete [] __buf;\\r
+               __buf = new TCHAR[nLen];\\r
+               nRes = GetDlgItemText(hwndDlg, _id, __buf, nLen);\\r
+       } while (nRes == nLen-1);\\r
+}\r
+\r
+/**\r
+ * \ingroup TortoiseShell\r
+ * Displays and updates all controls on the property page. The property\r
+ * page itself is shown by explorer.\r
+ */\r
+class CSVNPropertyPage\r
+{\r
+public:\r
+       CSVNPropertyPage(const std::vector<stdstring> &filenames);\r
+       virtual ~CSVNPropertyPage();\r
+\r
+       /**\r
+        * Sets the window handle.\r
+        * \param hwnd the handle.\r
+        */\r
+       virtual void SetHwnd(HWND hwnd);\r
+       /**\r
+        * Callback function which receives the window messages of the\r
+        * property page. See the Win32 API for PropertySheets for details.\r
+        */\r
+       virtual BOOL PageProc(HWND hwnd, UINT uMessage, WPARAM wParam, LPARAM lParam);\r
+\r
+protected:\r
+       /**\r
+        * Initializes the property page.\r
+        */\r
+       virtual void InitWorkfileView();\r
+       void Time64ToTimeString(__time64_t time, TCHAR * buf, size_t buflen);\r
+       \r
+       struct listproperty\r
+       {\r
+               stdstring name;\r
+               std::string value;\r
+               int               count;\r
+       };\r
+       HWND m_hwnd;\r
+       std::vector<stdstring> filenames;\r
+       std::map<stdstring, std::string> propmap;\r
+       TCHAR stringtablebuffer[255];\r
+};\r
+\r
+\r
diff --git a/TortoiseShell/ShellCache.h b/TortoiseShell/ShellCache.h
new file mode 100644 (file)
index 0000000..7cf2964
--- /dev/null
@@ -0,0 +1,634 @@
+// TortoiseSVN - a Windows shell extension for easy version control\r
+\r
+// Copyright (C) 2003-2008 - Stefan Kueng\r
+\r
+// This program is free software; you can redistribute it and/or\r
+// modify it under the terms of the GNU General Public License\r
+// as published by the Free Software Foundation; either version 2\r
+// of the License, or (at your option) any later version.\r
+\r
+// This program is distributed in the hope that it will be useful,\r
+// but WITHOUT ANY WARRANTY; without even the implied warranty of\r
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\r
+// GNU General Public License for more details.\r
+\r
+// You should have received a copy of the GNU General Public License\r
+// along with this program; if not, write to the Free Software Foundation,\r
+// 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.\r
+//\r
+#pragma once\r
+#include "registry.h"\r
+#include "Globals.h"\r
+#include "SVNAdminDir.h"\r
+\r
+#define REGISTRYTIMEOUT 2000\r
+#define EXCLUDELISTTIMEOUT 5000\r
+#define ADMINDIRTIMEOUT 10000\r
+#define DRIVETYPETIMEOUT 300000                // 5 min\r
+#define NUMBERFMTTIMEOUT 300000\r
+#define MENUTIMEOUT 100\r
+\r
+typedef CComCritSecLock<CComCriticalSection> Locker;\r
+\r
+/**\r
+ * \ingroup TortoiseShell\r
+ * Helper class which caches access to the registry. Also provides helper methods\r
+ * for checks against the settings stored in the registry.\r
+ */\r
+class ShellCache\r
+{\r
+public:\r
+       enum CacheType\r
+       {\r
+               none,\r
+               exe,\r
+               dll\r
+       };\r
+       ShellCache()\r
+       {\r
+               cachetype = CRegStdWORD(_T("Software\\TortoiseSVN\\CacheType"), GetSystemMetrics(SM_REMOTESESSION) ? dll : exe);\r
+               showrecursive = CRegStdWORD(_T("Software\\TortoiseSVN\\RecursiveOverlay"), TRUE);\r
+               folderoverlay = CRegStdWORD(_T("Software\\TortoiseSVN\\FolderOverlay"), TRUE);\r
+               driveremote = CRegStdWORD(_T("Software\\TortoiseSVN\\DriveMaskRemote"));\r
+               drivefixed = CRegStdWORD(_T("Software\\TortoiseSVN\\DriveMaskFixed"), TRUE);\r
+               drivecdrom = CRegStdWORD(_T("Software\\TortoiseSVN\\DriveMaskCDROM"));\r
+               driveremove = CRegStdWORD(_T("Software\\TortoiseSVN\\DriveMaskRemovable"));\r
+               drivefloppy = CRegStdWORD(_T("Software\\TortoiseSVN\\DriveMaskFloppy"));\r
+               driveram = CRegStdWORD(_T("Software\\TortoiseSVN\\DriveMaskRAM"));\r
+               driveunknown = CRegStdWORD(_T("Software\\TortoiseSVN\\DriveMaskUnknown"));\r
+               excludelist = CRegStdString(_T("Software\\TortoiseSVN\\OverlayExcludeList"));\r
+               includelist = CRegStdString(_T("Software\\TortoiseSVN\\OverlayIncludeList"));\r
+               simplecontext = CRegStdWORD(_T("Software\\TortoiseSVN\\SimpleContext"), FALSE);\r
+               unversionedasmodified = CRegStdWORD(_T("Software\\TortoiseSVN\\UnversionedAsModified"), FALSE);\r
+               showunversionedoverlay = CRegStdWORD(_T("Software\\TortoiseSVN\\ShowUnversionedOverlay"), TRUE);\r
+               showignoredoverlay = CRegStdWORD(_T("Software\\TortoiseSVN\\ShowIgnoredOverlay"), TRUE);\r
+               getlocktop = CRegStdWORD(_T("Software\\TortoiseSVN\\GetLockTop"), TRUE);\r
+               excludedasnormal = CRegStdWORD(_T("Software\\TortoiseSVN\\ShowExcludedAsNormal"), TRUE);\r
+               cachetypeticker = GetTickCount();\r
+               recursiveticker = cachetypeticker;\r
+               folderoverlayticker = cachetypeticker;\r
+               driveticker = cachetypeticker;\r
+               drivetypeticker = cachetypeticker;\r
+               langticker = cachetypeticker;\r
+               columnrevformatticker = cachetypeticker;\r
+               excludelistticker = cachetypeticker;\r
+               includelistticker = cachetypeticker;\r
+               simplecontextticker = cachetypeticker;\r
+               unversionedasmodifiedticker = cachetypeticker;\r
+               showunversionedoverlayticker = cachetypeticker;\r
+               showignoredoverlayticker = cachetypeticker;\r
+               admindirticker = cachetypeticker;\r
+               columnseverywhereticker = cachetypeticker;\r
+               getlocktopticker = cachetypeticker;\r
+               excludedasnormalticker = cachetypeticker;\r
+               excontextticker = cachetypeticker;\r
+               menulayoutlow = CRegStdWORD(_T("Software\\TortoiseSVN\\ContextMenuEntries"), MENUCHECKOUT | MENUUPDATE | MENUCOMMIT);\r
+               menulayouthigh = CRegStdWORD(_T("Software\\TortoiseSVN\\ContextMenuEntrieshigh"), 0);\r
+               menumasklow_lm = CRegStdWORD(_T("Software\\TortoiseSVN\\ContextMenuEntriesMaskLow"), 0, FALSE, HKEY_LOCAL_MACHINE);\r
+               menumaskhigh_lm = CRegStdWORD(_T("Software\\TortoiseSVN\\ContextMenuEntriesMaskHigh"), 0, FALSE, HKEY_LOCAL_MACHINE);\r
+               menumasklow_cu = CRegStdWORD(_T("Software\\TortoiseSVN\\ContextMenuEntriesMaskLow"), 0);\r
+               menumaskhigh_cu = CRegStdWORD(_T("Software\\TortoiseSVN\\ContextMenuEntriesMaskHigh"), 0);\r
+               langid = CRegStdWORD(_T("Software\\TortoiseSVN\\LanguageID"), 1033);\r
+               blockstatus = CRegStdWORD(_T("Software\\TortoiseSVN\\BlockStatus"), 0);\r
+               columnseverywhere = CRegStdWORD(_T("Software\\TortoiseSVN\\ColumnsEveryWhere"), FALSE);\r
+               for (int i=0; i<27; i++)\r
+               {\r
+                       drivetypecache[i] = (UINT)-1;\r
+               }\r
+               // A: and B: are floppy disks\r
+               drivetypecache[0] = DRIVE_REMOVABLE;\r
+               drivetypecache[1] = DRIVE_REMOVABLE;\r
+               TCHAR szBuffer[5];\r
+               columnrevformatticker = GetTickCount();\r
+               SecureZeroMemory(&columnrevformat, sizeof(NUMBERFMT));\r
+               GetLocaleInfo(LOCALE_USER_DEFAULT, LOCALE_SDECIMAL, &szDecSep[0], sizeof(szDecSep));\r
+               GetLocaleInfo(LOCALE_USER_DEFAULT, LOCALE_STHOUSAND, &szThousandsSep[0], sizeof(szThousandsSep));\r
+               columnrevformat.lpDecimalSep = szDecSep;\r
+               columnrevformat.lpThousandSep = szThousandsSep;\r
+               GetLocaleInfo(LOCALE_USER_DEFAULT, LOCALE_SGROUPING, &szBuffer[0], sizeof(szBuffer));\r
+               columnrevformat.Grouping = _ttoi(szBuffer);\r
+               GetLocaleInfo(LOCALE_USER_DEFAULT, LOCALE_INEGNUMBER, &szBuffer[0], sizeof(szBuffer));\r
+               columnrevformat.NegativeOrder = _ttoi(szBuffer);\r
+               sAdminDirCacheKey.reserve(MAX_PATH);            // MAX_PATH as buffer reservation ok.\r
+               nocontextpaths = CRegStdString(_T("Software\\TortoiseSVN\\NoContextPaths"), _T(""));\r
+               m_critSec.Init();\r
+       }\r
+       void ForceRefresh()\r
+       {\r
+               cachetype.read();\r
+               showrecursive.read();\r
+               folderoverlay.read();\r
+               driveremote.read();\r
+               drivefixed.read();\r
+               drivecdrom.read();\r
+               driveremove.read();\r
+               drivefloppy.read();\r
+               driveram.read();\r
+               driveunknown.read();\r
+               excludelist.read();\r
+               includelist.read();\r
+               simplecontext.read();\r
+               unversionedasmodified.read();\r
+               showunversionedoverlay.read();\r
+               showignoredoverlay.read();\r
+               excludedasnormal.read();\r
+               menulayoutlow.read();\r
+               menulayouthigh.read();\r
+               langid.read();\r
+               blockstatus.read();\r
+               columnseverywhere.read();\r
+               getlocktop.read();\r
+               menumasklow_lm.read();\r
+               menumaskhigh_lm.read();\r
+               menumasklow_cu.read();\r
+               menumaskhigh_cu.read();\r
+               nocontextpaths.read();\r
+       }\r
+       CacheType GetCacheType()\r
+       {\r
+               if ((GetTickCount() - REGISTRYTIMEOUT) > cachetypeticker)\r
+               {\r
+                       cachetypeticker = GetTickCount();\r
+                       cachetype.read();\r
+               }\r
+               return CacheType(DWORD((cachetype)));\r
+       }\r
+       DWORD BlockStatus()\r
+       {\r
+               if ((GetTickCount() - REGISTRYTIMEOUT) > blockstatusticker)\r
+               {\r
+                       blockstatusticker = GetTickCount();\r
+                       blockstatus.read();\r
+               }\r
+               return (blockstatus);\r
+       }\r
+       unsigned __int64 GetMenuLayout()\r
+       {\r
+               if ((GetTickCount() - REGISTRYTIMEOUT) > layoutticker)\r
+               {\r
+                       layoutticker = GetTickCount();\r
+                       menulayoutlow.read();\r
+                       menulayouthigh.read();\r
+               }\r
+               unsigned __int64 temp = unsigned __int64(DWORD(menulayouthigh))<<32;\r
+               temp |= unsigned __int64(DWORD(menulayoutlow));\r
+               return temp;\r
+       }\r
+       unsigned __int64 GetMenuMask()\r
+       {\r
+               if ((GetTickCount() - REGISTRYTIMEOUT) > menumaskticker)\r
+               {\r
+                       menumaskticker = GetTickCount();\r
+                       menumasklow_lm.read();\r
+                       menumaskhigh_lm.read();\r
+                       menumasklow_cu.read();\r
+                       menumaskhigh_cu.read();\r
+               }\r
+               DWORD low = (DWORD)menumasklow_lm | (DWORD)menumasklow_cu;\r
+               DWORD high = (DWORD)menumaskhigh_lm | (DWORD)menumaskhigh_cu;\r
+               unsigned __int64 temp = unsigned __int64(high)<<32;\r
+               temp |= unsigned __int64(low);\r
+               return temp;\r
+       }\r
+       BOOL IsRecursive()\r
+       {\r
+               if ((GetTickCount() - REGISTRYTIMEOUT)>recursiveticker)\r
+               {\r
+                       recursiveticker = GetTickCount();\r
+                       showrecursive.read();\r
+               }\r
+               return (showrecursive);\r
+       }\r
+       BOOL IsFolderOverlay()\r
+       {\r
+               if ((GetTickCount() - REGISTRYTIMEOUT)>folderoverlayticker)\r
+               {\r
+                       folderoverlayticker = GetTickCount();\r
+                       folderoverlay.read();\r
+               }\r
+               return (folderoverlay);\r
+       }\r
+       BOOL IsSimpleContext()\r
+       {\r
+               if ((GetTickCount() - REGISTRYTIMEOUT)>simplecontextticker)\r
+               {\r
+                       simplecontextticker = GetTickCount();\r
+                       simplecontext.read();\r
+               }\r
+               return (simplecontext!=0);\r
+       }\r
+       BOOL IsUnversionedAsModified()\r
+       {\r
+               if ((GetTickCount() - REGISTRYTIMEOUT)>unversionedasmodifiedticker)\r
+               {\r
+                       unversionedasmodifiedticker = GetTickCount();\r
+                       unversionedasmodified.read();\r
+               }\r
+               return (unversionedasmodified);\r
+       }\r
+       BOOL ShowUnversionedOverlay()\r
+       {\r
+               if ((GetTickCount() - REGISTRYTIMEOUT)>showunversionedoverlayticker)\r
+               {\r
+                       showunversionedoverlayticker = GetTickCount();\r
+                       showunversionedoverlay.read();\r
+               }\r
+               return (showunversionedoverlay);\r
+       }\r
+       BOOL ShowIgnoredOverlay()\r
+       {\r
+               if ((GetTickCount() - REGISTRYTIMEOUT)>showignoredoverlayticker)\r
+               {\r
+                       showignoredoverlayticker = GetTickCount();\r
+                       showignoredoverlay.read();\r
+               }\r
+               return (showignoredoverlay);\r
+       }\r
+       BOOL IsGetLockTop()\r
+       {\r
+               if ((GetTickCount() - REGISTRYTIMEOUT)>getlocktopticker)\r
+               {\r
+                       getlocktopticker = GetTickCount();\r
+                       getlocktop.read();\r
+               }\r
+               return (getlocktop);\r
+       }\r
+       BOOL ShowExcludedAsNormal()\r
+       {\r
+               if ((GetTickCount() - REGISTRYTIMEOUT)>excludedasnormalticker)\r
+               {\r
+                       excludedasnormalticker = GetTickCount();\r
+                       excludedasnormal.read();\r
+               }\r
+               return (excludedasnormal);\r
+       }\r
+       BOOL IsRemote()\r
+       {\r
+               DriveValid();\r
+               return (driveremote);\r
+       }\r
+       BOOL IsFixed()\r
+       {\r
+               DriveValid();\r
+               return (drivefixed);\r
+       }\r
+       BOOL IsCDRom()\r
+       {\r
+               DriveValid();\r
+               return (drivecdrom);\r
+       }\r
+       BOOL IsRemovable()\r
+       {\r
+               DriveValid();\r
+               return (driveremove);\r
+       }\r
+       BOOL IsRAM()\r
+       {\r
+               DriveValid();\r
+               return (driveram);\r
+       }\r
+       BOOL IsUnknown()\r
+       {\r
+               DriveValid();\r
+               return (driveunknown);\r
+       }\r
+       BOOL IsContextPathAllowed(LPCTSTR path)\r
+       {\r
+               Locker lock(m_critSec);\r
+               ExcludeContextValid();\r
+               for (std::vector<stdstring>::iterator I = excontextvector.begin(); I != excontextvector.end(); ++I)\r
+               {\r
+                       if (I->empty())\r
+                               continue;\r
+                       if (I->size() && I->at(I->size()-1)=='*')\r
+                       {\r
+                               stdstring str = I->substr(0, I->size()-1);\r
+                               if (_tcsnicmp(str.c_str(), path, str.size())==0)\r
+                                       return FALSE;\r
+                       }\r
+                       else if (_tcsicmp(I->c_str(), path)==0)\r
+                               return FALSE;\r
+               }\r
+               return TRUE;\r
+       }\r
+       BOOL IsPathAllowed(LPCTSTR path)\r
+       {\r
+               Locker lock(m_critSec);\r
+               IncludeListValid();\r
+               for (std::vector<stdstring>::iterator I = invector.begin(); I != invector.end(); ++I)\r
+               {\r
+                       if (I->empty())\r
+                               continue;\r
+                       if (I->at(I->size()-1)=='*')\r
+                       {\r
+                               stdstring str = I->substr(0, I->size()-1);\r
+                               if (_tcsnicmp(str.c_str(), path, str.size())==0)\r
+                                       return TRUE;\r
+                               if (str.size() && (str.at(str.size()-1) == '\\') && (_tcsnicmp(str.c_str(), path, str.size()-1)==0))\r
+                                       return TRUE;\r
+                       }\r
+                       else if (_tcsicmp(I->c_str(), path)==0)\r
+                               return TRUE;\r
+                       else if ((I->at(I->size()-1) == '\\') && \r
+                               ((_tcsnicmp(I->c_str(), path, I->size())==0) || (_tcsicmp(I->c_str(), path)==0)) )\r
+                               return TRUE;\r
+\r
+               }\r
+               UINT drivetype = 0;\r
+               int drivenumber = PathGetDriveNumber(path);\r
+               if ((drivenumber >=0)&&(drivenumber < 25))\r
+               {\r
+                       drivetype = drivetypecache[drivenumber];\r
+                       if ((drivetype == -1)||((GetTickCount() - DRIVETYPETIMEOUT)>drivetypeticker))\r
+                       {\r
+                               if ((drivenumber == 0)||(drivenumber == 1))\r
+                                       drivetypecache[drivenumber] = DRIVE_REMOVABLE;\r
+                               else\r
+                               {\r
+                                       drivetypeticker = GetTickCount();\r
+                                       TCHAR pathbuf[MAX_PATH+4];              // MAX_PATH ok here. PathStripToRoot works with partial paths too.\r
+                                       _tcsncpy_s(pathbuf, MAX_PATH+4, path, MAX_PATH+3);\r
+                                       PathStripToRoot(pathbuf);\r
+                                       PathAddBackslash(pathbuf);\r
+                                       ATLTRACE2(_T("GetDriveType for %s, Drive %d\n"), pathbuf, drivenumber);\r
+                                       drivetype = GetDriveType(pathbuf);\r
+                                       drivetypecache[drivenumber] = drivetype;\r
+                               }\r
+                       }\r
+               }\r
+               else\r
+               {\r
+                       TCHAR pathbuf[MAX_PATH+4];              // MAX_PATH ok here. PathIsUNCServer works with partial paths too.\r
+                       _tcsncpy_s(pathbuf, MAX_PATH+4, path, MAX_PATH+3);\r
+                       if (PathIsUNCServer(pathbuf))\r
+                               drivetype = DRIVE_REMOTE;\r
+                       else\r
+                       {\r
+                               PathStripToRoot(pathbuf);\r
+                               PathAddBackslash(pathbuf);\r
+                               if (_tcsncmp(pathbuf, drivetypepathcache, MAX_PATH-1)==0)               // MAX_PATH ok.\r
+                                       drivetype = drivetypecache[26];\r
+                               else\r
+                               {\r
+                                       ATLTRACE2(_T("GetDriveType for %s\n"), pathbuf);\r
+                                       drivetype = GetDriveType(pathbuf);\r
+                                       drivetypecache[26] = drivetype;\r
+                                       _tcsncpy_s(drivetypepathcache, MAX_PATH, pathbuf, MAX_PATH);                    // MAX_PATH ok.\r
+                               } \r
+                       }\r
+               }\r
+               if ((drivetype == DRIVE_REMOVABLE)&&(!IsRemovable()))\r
+                       return FALSE;\r
+               if ((drivetype == DRIVE_REMOVABLE)&&(drivefloppy == 0)&&((drivenumber==0)||(drivenumber==1)))\r
+                       return FALSE;\r
+               if ((drivetype == DRIVE_FIXED)&&(!IsFixed()))\r
+                       return FALSE;\r
+               if (((drivetype == DRIVE_REMOTE)||(drivetype == DRIVE_NO_ROOT_DIR))&&(!IsRemote()))\r
+                       return FALSE;\r
+               if ((drivetype == DRIVE_CDROM)&&(!IsCDRom()))\r
+                       return FALSE;\r
+               if ((drivetype == DRIVE_RAMDISK)&&(!IsRAM()))\r
+                       return FALSE;\r
+               if ((drivetype == DRIVE_UNKNOWN)&&(IsUnknown()))\r
+                       return FALSE;\r
+\r
+               ExcludeListValid();\r
+               for (std::vector<stdstring>::iterator I = exvector.begin(); I != exvector.end(); ++I)\r
+               {\r
+                       if (I->empty())\r
+                               continue;\r
+                       if (I->size() && I->at(I->size()-1)=='*')\r
+                       {\r
+                               stdstring str = I->substr(0, I->size()-1);\r
+                               if (_tcsnicmp(str.c_str(), path, str.size())==0)\r
+                                       return FALSE;\r
+                       }\r
+                       else if (_tcsicmp(I->c_str(), path)==0)\r
+                               return FALSE;\r
+               }\r
+               return TRUE;\r
+       }\r
+       DWORD GetLangID()\r
+       {\r
+               if ((GetTickCount() - REGISTRYTIMEOUT) > langticker)\r
+               {\r
+                       langticker = GetTickCount();\r
+                       langid.read();\r
+               }\r
+               return (langid);\r
+       }\r
+       NUMBERFMT * GetNumberFmt()\r
+       {\r
+               if ((GetTickCount() - NUMBERFMTTIMEOUT) > columnrevformatticker)\r
+               {\r
+                       TCHAR szBuffer[5];\r
+                       columnrevformatticker = GetTickCount();\r
+                       SecureZeroMemory(&columnrevformat, sizeof(NUMBERFMT));\r
+                       GetLocaleInfo(LOCALE_USER_DEFAULT, LOCALE_SDECIMAL, &szDecSep[0], sizeof(szDecSep));\r
+                       GetLocaleInfo(LOCALE_USER_DEFAULT, LOCALE_STHOUSAND, &szThousandsSep[0], sizeof(szThousandsSep));\r
+                       columnrevformat.lpDecimalSep = szDecSep;\r
+                       columnrevformat.lpThousandSep = szThousandsSep;\r
+                       GetLocaleInfo(LOCALE_USER_DEFAULT, LOCALE_SGROUPING, &szBuffer[0], sizeof(szBuffer));\r
+                       columnrevformat.Grouping = _ttoi(szBuffer);\r
+                       GetLocaleInfo(LOCALE_USER_DEFAULT, LOCALE_INEGNUMBER, &szBuffer[0], sizeof(szBuffer));\r
+                       columnrevformat.NegativeOrder = _ttoi(szBuffer);\r
+               }\r
+               return &columnrevformat;\r
+       }\r
+       BOOL HasSVNAdminDir(LPCTSTR path, BOOL bIsDir)\r
+       {\r
+               size_t len = _tcslen(path);\r
+               TCHAR * buf = new TCHAR[len+1];\r
+               _tcscpy_s(buf, len+1, path);\r
+               if (! bIsDir)\r
+               {\r
+                       TCHAR * ptr = _tcsrchr(buf, '\\');\r
+                       if (ptr != 0)\r
+                       {\r
+                               *ptr = 0;\r
+                       }\r
+               }\r
+               if ((GetTickCount() - ADMINDIRTIMEOUT) < admindirticker)\r
+               {\r
+                       std::map<stdstring, BOOL>::iterator iter;\r
+                       sAdminDirCacheKey.assign(buf);\r
+                       if ((iter = admindircache.find(sAdminDirCacheKey)) != admindircache.end())\r
+                       {\r
+                               delete [] buf;\r
+                               return iter->second;\r
+                       }\r
+               }\r
+               BOOL hasAdminDir = g_SVNAdminDir.HasAdminDir(buf, true);\r
+               admindirticker = GetTickCount();\r
+               Locker lock(m_critSec);\r
+               admindircache[buf] = hasAdminDir;\r
+               delete [] buf;\r
+               return hasAdminDir;\r
+       }\r
+       bool IsColumnsEveryWhere()\r
+       {\r
+               if ((GetTickCount() - REGISTRYTIMEOUT) > columnseverywhereticker)\r
+               {\r
+                       columnseverywhereticker = GetTickCount();\r
+                       columnseverywhere.read();\r
+               } \r
+               return !!(DWORD)columnseverywhere;\r
+       }\r
+private:\r
+       void DriveValid()\r
+       {\r
+               if ((GetTickCount() - REGISTRYTIMEOUT)>driveticker)\r
+               {\r
+                       driveticker = GetTickCount();\r
+                       driveremote.read();\r
+                       drivefixed.read();\r
+                       drivecdrom.read();\r
+                       driveremove.read();\r
+                       drivefloppy.read();\r
+               }\r
+       }\r
+       void ExcludeContextValid()\r
+       {\r
+               if ((GetTickCount() - EXCLUDELISTTIMEOUT)>excontextticker)\r
+               {\r
+                       Locker lock(m_critSec);\r
+                       excontextticker = GetTickCount();\r
+                       nocontextpaths.read();\r
+                       if (excludecontextstr.compare((stdstring)nocontextpaths)==0)\r
+                               return;\r
+                       excludecontextstr = (stdstring)nocontextpaths;\r
+                       excontextvector.clear();\r
+                       size_t pos = 0, pos_ant = 0;\r
+                       pos = excludecontextstr.find(_T("\n"), pos_ant);\r
+                       while (pos != stdstring::npos)\r
+                       {\r
+                               stdstring token = excludecontextstr.substr(pos_ant, pos-pos_ant);\r
+                               excontextvector.push_back(token);\r
+                               pos_ant = pos+1;\r
+                               pos = excludecontextstr.find(_T("\n"), pos_ant);\r
+                       }\r
+                       if (!excludecontextstr.empty())\r
+                       {\r
+                               excontextvector.push_back(excludecontextstr.substr(pos_ant, excludecontextstr.size()-1));\r
+                       }\r
+                       excludecontextstr = (stdstring)nocontextpaths;\r
+               }\r
+       }\r
+       void ExcludeListValid()\r
+       {\r
+               if ((GetTickCount() - EXCLUDELISTTIMEOUT)>excludelistticker)\r
+               {\r
+                       Locker lock(m_critSec);\r
+                       excludelistticker = GetTickCount();\r
+                       excludelist.read();\r
+                       if (excludeliststr.compare((stdstring)excludelist)==0)\r
+                               return;\r
+                       excludeliststr = (stdstring)excludelist;\r
+                       exvector.clear();\r
+                       size_t pos = 0, pos_ant = 0;\r
+                       pos = excludeliststr.find(_T("\n"), pos_ant);\r
+                       while (pos != stdstring::npos)\r
+                       {\r
+                               stdstring token = excludeliststr.substr(pos_ant, pos-pos_ant);\r
+                               exvector.push_back(token);\r
+                               pos_ant = pos+1;\r
+                               pos = excludeliststr.find(_T("\n"), pos_ant);\r
+                       }\r
+                       if (!excludeliststr.empty())\r
+                       {\r
+                               exvector.push_back(excludeliststr.substr(pos_ant, excludeliststr.size()-1));\r
+                       }\r
+                       excludeliststr = (stdstring)excludelist;\r
+               }\r
+       }\r
+       void IncludeListValid()\r
+       {\r
+               if ((GetTickCount() - EXCLUDELISTTIMEOUT)>includelistticker)\r
+               {\r
+                       Locker lock(m_critSec);\r
+                       includelistticker = GetTickCount();\r
+                       includelist.read();\r
+                       if (includeliststr.compare((stdstring)includelist)==0)\r
+                               return;\r
+                       includeliststr = (stdstring)includelist;\r
+                       invector.clear();\r
+                       size_t pos = 0, pos_ant = 0;\r
+                       pos = includeliststr.find(_T("\n"), pos_ant);\r
+                       while (pos != stdstring::npos)\r
+                       {\r
+                               stdstring token = includeliststr.substr(pos_ant, pos-pos_ant);\r
+                               invector.push_back(token);\r
+                               pos_ant = pos+1;\r
+                               pos = includeliststr.find(_T("\n"), pos_ant);\r
+                       }\r
+                       if (!includeliststr.empty())\r
+                       {\r
+                               invector.push_back(includeliststr.substr(pos_ant, includeliststr.size()-1));\r
+                       }\r
+                       includeliststr = (stdstring)includelist;\r
+               }\r
+       }\r
+       CRegStdWORD cachetype;\r
+       CRegStdWORD blockstatus;\r
+       CRegStdWORD langid;\r
+       CRegStdWORD showrecursive;\r
+       CRegStdWORD folderoverlay;\r
+       CRegStdWORD getlocktop;\r
+       CRegStdWORD driveremote;\r
+       CRegStdWORD drivefixed;\r
+       CRegStdWORD drivecdrom;\r
+       CRegStdWORD driveremove;\r
+       CRegStdWORD drivefloppy;\r
+       CRegStdWORD driveram;\r
+       CRegStdWORD driveunknown;\r
+       CRegStdWORD menulayoutlow;\r
+       CRegStdWORD menulayouthigh;\r
+       CRegStdWORD simplecontext;\r
+       CRegStdWORD menumasklow_lm;\r
+       CRegStdWORD menumaskhigh_lm;\r
+       CRegStdWORD menumasklow_cu;\r
+       CRegStdWORD menumaskhigh_cu;\r
+       CRegStdWORD unversionedasmodified;\r
+       CRegStdWORD showunversionedoverlay;\r
+       CRegStdWORD showignoredoverlay;\r
+       CRegStdWORD excludedasnormal;\r
+       CRegStdString excludelist;\r
+       CRegStdWORD columnseverywhere;\r
+       stdstring excludeliststr;\r
+       std::vector<stdstring> exvector;\r
+       CRegStdString includelist;\r
+       stdstring includeliststr;\r
+       std::vector<stdstring> invector;\r
+       DWORD cachetypeticker;\r
+       DWORD recursiveticker;\r
+       DWORD folderoverlayticker;\r
+       DWORD getlocktopticker;\r
+       DWORD driveticker;\r
+       DWORD drivetypeticker;\r
+       DWORD layoutticker;\r
+       DWORD menumaskticker;\r
+       DWORD langticker;\r
+       DWORD blockstatusticker;\r
+       DWORD columnrevformatticker;\r
+       DWORD excludelistticker;\r
+       DWORD includelistticker;\r
+       DWORD simplecontextticker;\r
+       DWORD unversionedasmodifiedticker;\r
+       DWORD showunversionedoverlayticker;\r
+       DWORD showignoredoverlayticker;\r
+       DWORD excludedasnormalticker;\r
+       DWORD columnseverywhereticker;\r
+       UINT  drivetypecache[27];\r
+       TCHAR drivetypepathcache[MAX_PATH];             // MAX_PATH ok.\r
+       NUMBERFMT columnrevformat;\r
+       TCHAR szDecSep[5];\r
+       TCHAR szThousandsSep[5];\r
+       std::map<stdstring, BOOL> admindircache;\r
+       stdstring sAdminDirCacheKey;\r
+       CRegStdString nocontextpaths;\r
+       stdstring excludecontextstr;\r
+       std::vector<stdstring> excontextvector;\r
+       DWORD excontextticker;\r
+       DWORD admindirticker;\r
+       CComCriticalSection m_critSec;\r
+};\r
diff --git a/TortoiseShell/ShellExt.cpp b/TortoiseShell/ShellExt.cpp
new file mode 100644 (file)
index 0000000..088ecba
--- /dev/null
@@ -0,0 +1,292 @@
+// TortoiseSVN - a Windows shell extension for easy version control\r
+\r
+// Copyright (C) 2003-2008 - TortoiseSVN\r
+\r
+// This program is free software; you can redistribute it and/or\r
+// modify it under the terms of the GNU General Public License\r
+// as published by the Free Software Foundation; either version 2\r
+// of the License, or (at your option) any later version.\r
+\r
+// This program is distributed in the hope that it will be useful,\r
+// but WITHOUT ANY WARRANTY; without even the implied warranty of\r
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\r
+// GNU General Public License for more details.\r
+\r
+// You should have received a copy of the GNU General Public License\r
+// along with this program; if not, write to the Free Software Foundation,\r
+// 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.\r
+//\r
+#include "stdafx.h"\r
+\r
+#pragma warning (disable : 4786)\r
+\r
+// Initialize GUIDs (should be done only and at-least once per DLL/EXE)\r
+#include <initguid.h>\r
+#include "Guids.h"\r
+\r
+#include "ShellExt.h"\r
+#include "..\version.h"\r
+#include "libintl.h"\r
+#undef swprintf\r
+\r
+std::set<CShellExt *> g_exts;\r
+\r
+\r
+// *********************** CShellExt *************************\r
+CShellExt::CShellExt(FileState state)\r
+{\r
+       OSVERSIONINFOEX inf;\r
+       SecureZeroMemory(&inf, sizeof(OSVERSIONINFOEX));\r
+       inf.dwOSVersionInfoSize = sizeof(OSVERSIONINFOEX);\r
+       GetVersionEx((OSVERSIONINFO *)&inf);\r
+       fullver = MAKEWORD(inf.dwMinorVersion, inf.dwMajorVersion);\r
+\r
+    m_State = state;\r
+\r
+    m_cRef = 0L;\r
+    g_cRefThisDll++;\r
+\r
+       g_exts.insert(this);\r
+       \r
+    INITCOMMONCONTROLSEX used = {\r
+        sizeof(INITCOMMONCONTROLSEX),\r
+                       ICC_LISTVIEW_CLASSES | ICC_WIN95_CLASSES | ICC_BAR_CLASSES | ICC_USEREX_CLASSES\r
+    };\r
+    InitCommonControlsEx(&used);\r
+       LoadLangDll();\r
+\r
+       if (fullver >= 0x0600)\r
+       {\r
+               HMODULE hUxTheme = ::GetModuleHandle (_T("UXTHEME.DLL"));\r
+\r
+               pfnGetBufferedPaintBits = (FN_GetBufferedPaintBits)::GetProcAddress(hUxTheme, "GetBufferedPaintBits");\r
+               pfnBeginBufferedPaint = (FN_BeginBufferedPaint)::GetProcAddress(hUxTheme, "BeginBufferedPaint");\r
+               pfnEndBufferedPaint = (FN_EndBufferedPaint)::GetProcAddress(hUxTheme, "EndBufferedPaint");\r
+       }\r
+}\r
+\r
+CShellExt::~CShellExt()\r
+{\r
+       std::map<UINT, HBITMAP>::iterator it;\r
+       for (it = bitmaps.begin(); it != bitmaps.end(); ++it)\r
+       {\r
+               ::DeleteObject(it->second);\r
+       }\r
+       bitmaps.clear();\r
+       g_cRefThisDll--;\r
+       g_exts.erase(this);\r
+}\r
+\r
+void LoadLangDll()\r
+{\r
+       if ((g_langid != g_ShellCache.GetLangID())&&((g_langTimeout == 0)||(g_langTimeout < GetTickCount())))\r
+       {\r
+               g_langid = g_ShellCache.GetLangID();\r
+               DWORD langId = g_langid;\r
+               TCHAR langDll[MAX_PATH*4];\r
+               HINSTANCE hInst = NULL;\r
+               TCHAR langdir[MAX_PATH] = {0};\r
+               char langdirA[MAX_PATH] = {0};\r
+               if (GetModuleFileName(g_hmodThisDll, langdir, MAX_PATH)==0)\r
+                       return;\r
+               if (GetModuleFileNameA(g_hmodThisDll, langdirA, MAX_PATH)==0)\r
+                       return;\r
+               TCHAR * dirpoint = _tcsrchr(langdir, '\\');\r
+               char * dirpointA = strrchr(langdirA, '\\');\r
+               if (dirpoint)\r
+                       *dirpoint = 0;\r
+               if (dirpointA)\r
+                       *dirpointA = 0;\r
+               dirpoint = _tcsrchr(langdir, '\\');\r
+               dirpointA = strrchr(langdirA, '\\');\r
+               if (dirpoint)\r
+                       *dirpoint = 0;\r
+               if (dirpointA)\r
+                       *dirpointA = 0;\r
+               strcat_s(langdirA, MAX_PATH, "\\Languages");\r
+               bindtextdomain ("subversion", langdirA);\r
+\r
+               do\r
+               {\r
+                       _stprintf_s(langDll, MAX_PATH*4, _T("%s\\Languages\\TortoiseProc%d.dll"), langdir, langId);\r
+                       BOOL versionmatch = TRUE;\r
+\r
+                       struct TRANSARRAY\r
+                       {\r
+                               WORD wLanguageID;\r
+                               WORD wCharacterSet;\r
+                       };\r
+\r
+                       DWORD dwReserved,dwBufferSize;\r
+                       dwBufferSize = GetFileVersionInfoSize((LPTSTR)langDll,&dwReserved);\r
+\r
+                       if (dwBufferSize > 0)\r
+                       {\r
+                               LPVOID pBuffer = (void*) malloc(dwBufferSize);\r
+\r
+                               if (pBuffer != (void*) NULL)\r
+                               {\r
+                                       UINT        nInfoSize = 0,\r
+                                               nFixedLength = 0;\r
+                                       LPSTR       lpVersion = NULL;\r
+                                       VOID*       lpFixedPointer;\r
+                                       TRANSARRAY* lpTransArray;\r
+                                       TCHAR       strLangProduktVersion[MAX_PATH];\r
+\r
+                                       if (GetFileVersionInfo((LPTSTR)langDll,\r
+                                               dwReserved,\r
+                                               dwBufferSize,\r
+                                               pBuffer))\r
+                                       {\r
+                                               // Query the current language\r
+                                               if (VerQueryValue(      pBuffer,\r
+                                                       _T("\\VarFileInfo\\Translation"),\r
+                                                       &lpFixedPointer,\r
+                                                       &nFixedLength))\r
+                                               {\r
+                                                       lpTransArray = (TRANSARRAY*) lpFixedPointer;\r
+\r
+                                                       _stprintf_s(strLangProduktVersion, MAX_PATH, _T("\\StringFileInfo\\%04x%04x\\ProductVersion"),\r
+                                                               lpTransArray[0].wLanguageID, lpTransArray[0].wCharacterSet);\r
+\r
+                                                       if (VerQueryValue(pBuffer,\r
+                                                               (LPTSTR)strLangProduktVersion,\r
+                                                               (LPVOID *)&lpVersion,\r
+                                                               &nInfoSize))\r
+                                                       {\r
+                                                               versionmatch = (_tcscmp((LPCTSTR)lpVersion, _T(STRPRODUCTVER)) == 0);\r
+                                                       }\r
+\r
+                                               }\r
+                                       }\r
+                                       free(pBuffer);\r
+                               } // if (pBuffer != (void*) NULL) \r
+                       } // if (dwBufferSize > 0) \r
+                       else\r
+                               versionmatch = FALSE; \r
+\r
+                       if (versionmatch)\r
+                               hInst = LoadLibrary(langDll);\r
+                       if (hInst != NULL)\r
+                       {\r
+                               if (g_hResInst != g_hmodThisDll)\r
+                                       FreeLibrary(g_hResInst);\r
+                               g_hResInst = hInst;\r
+                       }\r
+                       else\r
+                       {\r
+                               DWORD lid = SUBLANGID(langId);\r
+                               lid--;\r
+                               if (lid > 0)\r
+                               {\r
+                                       langId = MAKELANGID(PRIMARYLANGID(langId), lid);\r
+                               }\r
+                               else\r
+                                       langId = 0;\r
+                       } \r
+               } while ((hInst == NULL) && (langId != 0));\r
+               if (hInst == NULL)\r
+               {\r
+                       // either the dll for the selected language is not present, or\r
+                       // it is the wrong version.\r
+                       // fall back to English and set a timeout so we don't retry\r
+                       // to load the language dll too often\r
+                       if (g_hResInst != g_hmodThisDll)\r
+                               FreeLibrary(g_hResInst);\r
+                       g_hResInst = g_hmodThisDll;\r
+                       g_langid = 1033;\r
+                       // set a timeout of 10 seconds\r
+                       if (g_ShellCache.GetLangID() != 1033)\r
+                               g_langTimeout = GetTickCount() + 10000;\r
+               }\r
+               else\r
+                       g_langTimeout = 0;\r
+       } // if (g_langid != g_ShellCache.GetLangID()) \r
+}\r
+\r
+STDMETHODIMP CShellExt::QueryInterface(REFIID riid, LPVOID FAR *ppv)\r
+{\r
+    *ppv = NULL; \r
+\r
+    if (IsEqualIID(riid, IID_IShellExtInit) || IsEqualIID(riid, IID_IUnknown))\r
+    {\r
+        *ppv = (LPSHELLEXTINIT)this;\r
+    }\r
+    else if (IsEqualIID(riid, IID_IContextMenu))\r
+    {\r
+        *ppv = (LPCONTEXTMENU)this;\r
+    }\r
+    else if (IsEqualIID(riid, IID_IContextMenu2))\r
+    {\r
+        *ppv = (LPCONTEXTMENU2)this;\r
+    }\r
+    else if (IsEqualIID(riid, IID_IContextMenu3))\r
+    {\r
+        *ppv = (LPCONTEXTMENU3)this;\r
+    }\r
+    else if (IsEqualIID(riid, IID_IShellIconOverlayIdentifier))\r
+    {\r
+        *ppv = (IShellIconOverlayIdentifier*)this;\r
+    }\r
+    else if (IsEqualIID(riid, IID_IShellPropSheetExt))\r
+    {\r
+        *ppv = (LPSHELLPROPSHEETEXT)this;\r
+    }\r
+       else if (IsEqualIID(riid, IID_IColumnProvider)) \r
+       { \r
+               *ppv = (IColumnProvider *)this;\r
+       } \r
+       else if (IsEqualIID(riid, IID_IShellCopyHook))\r
+       {\r
+               *ppv = (ICopyHook *)this;\r
+       }\r
+    if (*ppv)\r
+    {\r
+        AddRef();\r
+               \r
+        return NOERROR;\r
+    }\r
+       \r
+    return E_NOINTERFACE;\r
+}\r
+\r
+STDMETHODIMP_(ULONG) CShellExt::AddRef()\r
+{\r
+    return ++m_cRef;\r
+}\r
+\r
+STDMETHODIMP_(ULONG) CShellExt::Release()\r
+{\r
+    if (--m_cRef)\r
+        return m_cRef;\r
+       \r
+    delete this;\r
+       \r
+    return 0L;\r
+}\r
+\r
+// IPersistFile members\r
+STDMETHODIMP CShellExt::GetClassID(CLSID *pclsid) \r
+{\r
+    *pclsid = CLSID_TortoiseSVN_UNCONTROLLED;\r
+    return S_OK;\r
+}\r
+\r
+STDMETHODIMP CShellExt::Load(LPCOLESTR /*pszFileName*/, DWORD /*dwMode*/)\r
+{\r
+    return S_OK;\r
+}\r
+\r
+// ICopyHook member\r
+UINT __stdcall CShellExt::CopyCallback(HWND /*hWnd*/, UINT wFunc, UINT /*wFlags*/, LPCTSTR pszSrcFile, DWORD /*dwSrcAttribs*/, LPCTSTR /*pszDestFile*/, DWORD /*dwDestAttribs*/)\r
+{\r
+       if (wFunc == FO_COPY)\r
+               return IDYES;   // copying is not a problem for us\r
+\r
+       m_remoteCacheLink.ReleaseLockForPath(CTSVNPath(pszSrcFile));\r
+       // we could now wait a little bit to give the cache time to release the handles.\r
+       // but the explorer/shell already retries any action for about two seconds\r
+       // if it first fails. So if the cache hasn't released the handle yet, the explorer\r
+       // will retry anyway, so we just leave here immediately.\r
+       return IDYES;\r
+}\r
diff --git a/TortoiseShell/ShellExt.def b/TortoiseShell/ShellExt.def
new file mode 100644 (file)
index 0000000..455320d
--- /dev/null
@@ -0,0 +1,7 @@
+;shellext.def : Declares the module parameters for the DLL.\r
+\r
+LIBRARY      TORTOISESVN\r
+\r
+EXPORTS\r
+    DllCanUnloadNow private\r
+    DllGetClassObject private\r
diff --git a/TortoiseShell/ShellExt.h b/TortoiseShell/ShellExt.h
new file mode 100644 (file)
index 0000000..22521ee
--- /dev/null
@@ -0,0 +1,308 @@
+// TortoiseSVN - a Windows shell extension for easy version control\r
+\r
+// Copyright (C) 2003-2008 - TortoiseSVN\r
+\r
+// This program is free software; you can redistribute it and/or\r
+// modify it under the terms of the GNU General Public License\r
+// as published by the Free Software Foundation; either version 2\r
+// of the License, or (at your option) any later version.\r
+\r
+// This program is distributed in the hope that it will be useful,\r
+// but WITHOUT ANY WARRANTY; without even the implied warranty of\r
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\r
+// GNU General Public License for more details.\r
+\r
+// You should have received a copy of the GNU General Public License\r
+// along with this program; if not, write to the Free Software Foundation,\r
+// 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.\r
+//\r
+#pragma once\r
+\r
+#include "Globals.h"\r
+#include "registry.h"\r
+#include "resource.h"\r
+#include "ShellCache.h"\r
+#include "RemoteCacheLink.h"\r
+#include "SVNFolderStatus.h"\r
+#include "uxtheme.h"\r
+\r
+extern UINT                            g_cRefThisDll;                  // Reference count of this DLL.\r
+extern HINSTANCE                       g_hmodThisDll;                  // Instance handle for this DLL\r
+extern ShellCache                      g_ShellCache;                   // caching of registry entries, ...\r
+extern DWORD                           g_langid;\r
+extern DWORD                           g_langTimeout;\r
+extern HINSTANCE                       g_hResInst;\r
+extern stdstring                       g_filepath;\r
+extern svn_wc_status_kind      g_filestatus;                   ///< holds the corresponding status to the file/dir above\r
+extern  bool                           g_readonlyoverlay;              ///< whether to show the read only overlay or not\r
+extern bool                            g_lockedoverlay;                ///< whether to show the locked overlay or not\r
+\r
+extern bool                                    g_normalovlloaded;\r
+extern bool                                    g_modifiedovlloaded;\r
+extern bool                                    g_conflictedovlloaded;\r
+extern bool                                    g_readonlyovlloaded;\r
+extern bool                                    g_deletedovlloaded;\r
+extern bool                                    g_lockedovlloaded;\r
+extern bool                                    g_addedovlloaded;\r
+extern bool                                    g_ignoredovlloaded;\r
+extern bool                                    g_unversionedovlloaded;\r
+extern LPCTSTR                         g_MenuIDString;\r
+\r
+extern void                            LoadLangDll();\r
+extern  CComCriticalSection    g_csGlobalCOMGuard;\r
+typedef CComCritSecLock<CComCriticalSection> AutoLocker;\r
+\r
+typedef DWORD ARGB;\r
+\r
+typedef HRESULT (WINAPI *FN_GetBufferedPaintBits) (HPAINTBUFFER hBufferedPaint, RGBQUAD **ppbBuffer, int *pcxRow);\r
+typedef HPAINTBUFFER (WINAPI *FN_BeginBufferedPaint) (HDC hdcTarget, const RECT *prcTarget, BP_BUFFERFORMAT dwFormat, BP_PAINTPARAMS *pPaintParams, HDC *phdc);\r
+typedef HRESULT (WINAPI *FN_EndBufferedPaint) (HPAINTBUFFER hBufferedPaint, BOOL fUpdateTarget);\r
+\r
+\r
+// The actual OLE Shell context menu handler\r
+/**\r
+ * \ingroup TortoiseShell\r
+ * The main class of our COM object / Shell Extension.\r
+ * It contains all Interfaces we implement for the shell to use.\r
+ * \remark The implementations of the different interfaces are\r
+ * split into several *.cpp files to keep them in a reasonable size.\r
+ */\r
+class CShellExt : public IContextMenu3,\r
+                                                       IPersistFile,\r
+                                                       IColumnProvider,\r
+                                                       IShellExtInit,\r
+                                                       IShellIconOverlayIdentifier,\r
+                                                       IShellPropSheetExt,\r
+                                                       ICopyHookW\r
+\r
+// COMPILER ERROR? You need the latest version of the\r
+// platform SDK which has references to IColumnProvider \r
+// in the header files.  Download it here:\r
+// http://www.microsoft.com/msdownload/platformsdk/sdkupdate/\r
+{\r
+protected:\r
+\r
+       enum SVNCommands\r
+       {\r
+               ShellSeparator = 0,\r
+               ShellSubMenu = 1,\r
+               ShellSubMenuFolder,\r
+               ShellSubMenuFile,\r
+               ShellSubMenuLink,\r
+               ShellSubMenuMultiple,\r
+               ShellMenuCheckout,\r
+               ShellMenuUpdate,\r
+               ShellMenuCommit,\r
+               ShellMenuAdd,\r
+               ShellMenuAddAsReplacement,\r
+               ShellMenuRevert,\r
+               ShellMenuCleanup,\r
+               ShellMenuResolve,\r
+               ShellMenuSwitch,\r
+               ShellMenuImport,\r
+               ShellMenuExport,\r
+               ShellMenuAbout,\r
+               ShellMenuCreateRepos,\r
+               ShellMenuCopy,\r
+               ShellMenuMerge,\r
+               ShellMenuMergeAll,\r
+               ShellMenuSettings,\r
+               ShellMenuRemove,\r
+               ShellMenuRemoveKeep,\r
+               ShellMenuRename,\r
+               ShellMenuUpdateExt,\r
+               ShellMenuDiff,\r
+               ShellMenuPrevDiff,\r
+               ShellMenuUrlDiff,\r
+               ShellMenuDropCopyAdd,\r
+               ShellMenuDropMoveAdd,\r
+               ShellMenuDropMove,\r
+               ShellMenuDropMoveRename,\r
+               ShellMenuDropCopy,\r
+               ShellMenuDropCopyRename,\r
+               ShellMenuDropExport,\r
+               ShellMenuDropExportExtended,\r
+               ShellMenuLog,\r
+               ShellMenuConflictEditor,\r
+               ShellMenuRelocate,\r
+               ShellMenuHelp,\r
+               ShellMenuShowChanged,\r
+               ShellMenuIgnoreSub,\r
+               ShellMenuIgnore,\r
+               ShellMenuIgnoreFile,\r
+               ShellMenuIgnoreCaseSensitive,\r
+               ShellMenuIgnoreCaseInsensitive,\r
+               ShellMenuRepoBrowse,\r
+               ShellMenuBlame,\r
+               ShellMenuApplyPatch,\r
+               ShellMenuCreatePatch,\r
+               ShellMenuRevisionGraph,\r
+               ShellMenuUnIgnoreSub,\r
+               ShellMenuUnIgnoreCaseSensitive,\r
+               ShellMenuUnIgnore,\r
+               ShellMenuLock,\r
+               ShellMenuUnlock,\r
+               ShellMenuUnlockForce,\r
+               ShellMenuProperties,\r
+               ShellMenuDelUnversioned,\r
+               ShellMenuClipPaste,\r
+               ShellMenuLastEntry                      // used to mark the menu array end\r
+       };\r
+\r
+       // helper struct for context menu entries\r
+       typedef struct MenuInfo\r
+       {\r
+               SVNCommands                     command;                ///< the command which gets executed for this menu entry\r
+               unsigned __int64        menuID;                 ///< the menu ID to recognize the entry. NULL if it shouldn't be added to the context menu automatically\r
+               UINT                            iconID;                 ///< the icon to show for the menu entry\r
+               UINT                            menuTextID;             ///< the text of the menu entry\r
+               UINT                            menuDescID;             ///< the description text for the menu entry\r
+               /// the following 8 params are for checking whether the menu entry should\r
+               /// be added automatically, based on states of the selected item(s).\r
+               /// The 'yes' states must be set, the 'no' states must not be set\r
+               /// the four pairs are OR'ed together, the 'yes'/'no' states are AND'ed together.\r
+               DWORD                           firstyes;\r
+               DWORD                           firstno;\r
+               DWORD                           secondyes;\r
+               DWORD                           secondno;\r
+               DWORD                           thirdyes;\r
+               DWORD                           thirdno;\r
+               DWORD                           fourthyes;\r
+               DWORD                           fourthno;\r
+       };\r
+\r
+       static MenuInfo menuInfo[];\r
+       WORD fullver;\r
+       FileState m_State;\r
+       ULONG   m_cRef;\r
+       //std::map<int,std::string> verbMap;\r
+       std::map<UINT_PTR, UINT_PTR>    myIDMap;\r
+       std::map<UINT_PTR, UINT_PTR>    mySubMenuMap;\r
+       std::map<stdstring, UINT_PTR> myVerbsMap;\r
+       std::map<UINT_PTR, stdstring> myVerbsIDMap;\r
+       stdstring       folder_;\r
+       std::vector<stdstring> files_;\r
+       DWORD itemStates;                               ///< see the globals.h file for the ITEMIS_* defines\r
+       DWORD itemStatesFolder;                 ///< used for states of the folder_ (folder background and/or drop target folder)\r
+       stdstring uuidSource;\r
+       stdstring uuidTarget;\r
+       int space;\r
+       TCHAR stringtablebuffer[255];\r
+       stdstring columnfilepath;               ///< holds the last file/dir path for the column provider\r
+       stdstring columnauthor;                 ///< holds the corresponding author of the file/dir above\r
+       stdstring itemurl;\r
+       stdstring itemshorturl;\r
+       stdstring ignoredprops;\r
+       stdstring owner;\r
+       svn_revnum_t columnrev;                 ///< holds the corresponding revision to the file/dir above\r
+       svn_wc_status_kind      filestatus;\r
+       std::map<UINT, HBITMAP> bitmaps;\r
+\r
+       SVNFolderStatus         m_CachedStatus;         // status cache\r
+       CRemoteCacheLink        m_remoteCacheLink;\r
+\r
+       FN_GetBufferedPaintBits pfnGetBufferedPaintBits;\r
+       FN_BeginBufferedPaint pfnBeginBufferedPaint;\r
+       FN_EndBufferedPaint pfnEndBufferedPaint;\r
+\r
+#define MAKESTRING(ID) LoadStringEx(g_hResInst, ID, stringtablebuffer, sizeof(stringtablebuffer)/sizeof(TCHAR), (WORD)CRegStdWORD(_T("Software\\TortoiseSVN\\LanguageID"), MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT)))\r
+private:\r
+       void                    InsertSVNMenu(BOOL istop, HMENU menu, UINT pos, UINT_PTR id, UINT stringid, UINT icon, UINT idCmdFirst, SVNCommands com, UINT uFlags);\r
+       void                    InsertIgnoreSubmenus(UINT &idCmd, UINT idCmdFirst, HMENU hMenu, HMENU subMenu, UINT &indexMenu, int &indexSubMenu, unsigned __int64 topmenu, bool bShowIcons);\r
+       stdstring               WriteFileListToTempFile();\r
+       bool                    WriteClipboardPathsToTempFile(stdstring& tempfile);\r
+       LPCTSTR                 GetMenuTextFromResource(int id);\r
+       void                    GetColumnStatus(const TCHAR * path, BOOL bIsDir);\r
+       HBITMAP                 IconToBitmap(UINT uIcon);\r
+       STDMETHODIMP    QueryDropContext(UINT uFlags, UINT idCmdFirst, HMENU hMenu, UINT &indexMenu);\r
+       bool                    IsIllegalFolder(std::wstring folder, int * cslidarray);\r
+       HBITMAP                 IconToBitmapPARGB32(UINT uIcon);\r
+       HRESULT                 Create32BitHBITMAP(HDC hdc, const SIZE *psize, __deref_opt_out void **ppvBits, __out HBITMAP* phBmp);\r
+       HRESULT                 ConvertBufferToPARGB32(HPAINTBUFFER hPaintBuffer, HDC hdc, HICON hicon, SIZE& sizIcon);\r
+       bool                    HasAlpha(__in ARGB *pargb, SIZE& sizImage, int cxRow);\r
+       HRESULT                 ConvertToPARGB32(HDC hdc, __inout ARGB *pargb, HBITMAP hbmp, SIZE& sizImage, int cxRow);\r
+\r
+\r
+public:\r
+       CShellExt(FileState state);\r
+       virtual ~CShellExt();\r
+\r
+       /** \name IUnknown \r
+        * IUnknown members\r
+        */\r
+       //@{\r
+       STDMETHODIMP         QueryInterface(REFIID, LPVOID FAR *);\r
+       STDMETHODIMP_(ULONG) AddRef();\r
+       STDMETHODIMP_(ULONG) Release();\r
+       //@}\r
+\r
+       /** \name IContextMenu2 \r
+        * IContextMenu2 members\r
+        */\r
+       //@{\r
+       STDMETHODIMP    QueryContextMenu(HMENU hMenu, UINT indexMenu, UINT idCmdFirst, UINT idCmdLast, UINT uFlags);\r
+       STDMETHODIMP    InvokeCommand(LPCMINVOKECOMMANDINFO lpcmi);\r
+       STDMETHODIMP    GetCommandString(UINT_PTR idCmd, UINT uFlags, UINT FAR *reserved, LPSTR pszName, UINT cchMax);\r
+       STDMETHODIMP    HandleMenuMsg(UINT uMsg, WPARAM wParam, LPARAM lParam);\r
+       //@}\r
+\r
+    /** \name IContextMenu3 \r
+        * IContextMenu3 members\r
+        */\r
+       //@{\r
+       STDMETHODIMP    HandleMenuMsg2(UINT uMsg, WPARAM wParam, LPARAM lParam, LRESULT *pResult);\r
+       //@}\r
+\r
+       /** \name IColumnProvider\r
+        * IColumnProvider members\r
+        */\r
+       //@{\r
+       STDMETHODIMP    GetColumnInfo(DWORD dwIndex, SHCOLUMNINFO *psci);\r
+       STDMETHODIMP    GetItemData(LPCSHCOLUMNID pscid, LPCSHCOLUMNDATA pscd, VARIANT *pvarData);\r
+       STDMETHODIMP    Initialize(LPCSHCOLUMNINIT psci);\r
+       //@}\r
+\r
+       /** \name IShellExtInit\r
+        * IShellExtInit methods\r
+        */\r
+       //@{\r
+       STDMETHODIMP    Initialize(LPCITEMIDLIST pIDFolder, LPDATAOBJECT pDataObj, HKEY hKeyID);\r
+       //@}\r
+\r
+    /** \name IPersistFile\r
+        * IPersistFile methods\r
+        */\r
+       //@{\r
+    STDMETHODIMP       GetClassID(CLSID *pclsid);\r
+    STDMETHODIMP       Load(LPCOLESTR pszFileName, DWORD dwMode);\r
+    STDMETHODIMP       IsDirty(void) { return S_OK; };\r
+    STDMETHODIMP       Save(LPCOLESTR /*pszFileName*/, BOOL /*fRemember*/) { return S_OK; };\r
+    STDMETHODIMP       SaveCompleted(LPCOLESTR /*pszFileName*/) { return S_OK; };\r
+    STDMETHODIMP       GetCurFile(LPOLESTR * /*ppszFileName*/) { return S_OK; };\r
+       //@}\r
+\r
+       /** \name IShellIconOverlayIdentifier \r
+        * IShellIconOverlayIdentifier methods\r
+        */\r
+       //@{\r
+       STDMETHODIMP    GetOverlayInfo(LPWSTR pwszIconFile, int cchMax, int *pIndex, DWORD *pdwFlags);\r
+       STDMETHODIMP    GetPriority(int *pPriority); \r
+       STDMETHODIMP    IsMemberOf(LPCWSTR pwszPath, DWORD dwAttrib);\r
+       //@}\r
+\r
+       /** \name IShellPropSheetExt \r
+        * IShellPropSheetExt methods\r
+        */\r
+       //@{\r
+       STDMETHODIMP    AddPages(LPFNADDPROPSHEETPAGE lpfnAddPage, LPARAM lParam);\r
+       STDMETHODIMP    ReplacePage (UINT, LPFNADDPROPSHEETPAGE, LPARAM);\r
+       //@}\r
+\r
+       /** \name ICopyHook \r
+        * ICopyHook members\r
+        */\r
+       //@{\r
+       STDMETHODIMP_(UINT) CopyCallback(HWND hWnd, UINT wFunc, UINT wFlags, LPCTSTR pszSrcFile, DWORD dwSrcAttribs, LPCTSTR pszDestFile, DWORD dwDestAttribs);\r
+       //@}\r
+\r
+};\r
diff --git a/TortoiseShell/ShellExtClassFactory.cpp b/TortoiseShell/ShellExtClassFactory.cpp
new file mode 100644 (file)
index 0000000..1e8c235
--- /dev/null
@@ -0,0 +1,100 @@
+// TortoiseSVN - a Windows shell extension for easy version control\r
+\r
+// Copyright (C) 2003-2006 - Stefan Kueng\r
+\r
+// This program is free software; you can redistribute it and/or\r
+// modify it under the terms of the GNU General Public License\r
+// as published by the Free Software Foundation; either version 2\r
+// of the License, or (at your option) any later version.\r
+\r
+// This program is distributed in the hope that it will be useful,\r
+// but WITHOUT ANY WARRANTY; without even the implied warranty of\r
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\r
+// GNU General Public License for more details.\r
+\r
+// You should have received a copy of the GNU General Public License\r
+// along with this program; if not, write to the Free Software Foundation,\r
+// 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.\r
+//\r
+#include "stdafx.h"\r
+#include "ShellExt.h"\r
+#include "ShellExtClassFactory.h"\r
+\r
+extern std::set<CShellExt *> g_exts;\r
+\r
+CShellExtClassFactory::CShellExtClassFactory(FileState state)\r
+{\r
+    m_StateToMake = state;\r
+\r
+    m_cRef = 0L;\r
+       \r
+    g_cRefThisDll++; \r
+}\r
+\r
+CShellExtClassFactory::~CShellExtClassFactory()          \r
+{\r
+    g_cRefThisDll--;\r
+}\r
+\r
+STDMETHODIMP CShellExtClassFactory::QueryInterface(REFIID riid,\r
+                                                   LPVOID FAR *ppv)\r
+{\r
+    *ppv = NULL;\r
+\r
+    // Any interface on this object is the object pointer\r
+       \r
+    if (IsEqualIID(riid, IID_IUnknown) || IsEqualIID(riid, IID_IClassFactory))\r
+    {\r
+        *ppv = (LPCLASSFACTORY)this;\r
+               \r
+        AddRef();\r
+               \r
+        return NOERROR;\r
+    }\r
+       \r
+    return E_NOINTERFACE;\r
+}  \r
+\r
+STDMETHODIMP_(ULONG) CShellExtClassFactory::AddRef()\r
+{\r
+    return ++m_cRef;\r
+}\r
+\r
+STDMETHODIMP_(ULONG) CShellExtClassFactory::Release()\r
+{\r
+    if (--m_cRef)\r
+        return m_cRef;\r
+\r
+    delete this;\r
+       \r
+    return 0L;\r
+}\r
+\r
+STDMETHODIMP CShellExtClassFactory::CreateInstance(LPUNKNOWN pUnkOuter,\r
+                                                                                                  REFIID riid,\r
+                                                                                                  LPVOID *ppvObj)\r
+{\r
+    *ppvObj = NULL;\r
+       \r
+    // Shell extensions typically don't support aggregation (inheritance)\r
+       \r
+    if (pUnkOuter)\r
+        return CLASS_E_NOAGGREGATION;\r
+       \r
+    // Create the main shell extension object.  The shell will then call\r
+    // QueryInterface with IID_IShellExtInit--this is how shell extensions are\r
+    // initialized.\r
+       \r
+    CShellExt* pShellExt = new CShellExt(m_StateToMake);  //Create the CShellExt object\r
+               \r
+    if (NULL == pShellExt)\r
+        return E_OUTOFMEMORY;\r
+       \r
+    return pShellExt->QueryInterface(riid, ppvObj);\r
+}\r
+\r
+\r
+STDMETHODIMP CShellExtClassFactory::LockServer(BOOL /*fLock*/)\r
+{\r
+    return E_NOTIMPL;\r
+}\r
diff --git a/TortoiseShell/ShellExtClassFactory.h b/TortoiseShell/ShellExtClassFactory.h
new file mode 100644 (file)
index 0000000..68d0e17
--- /dev/null
@@ -0,0 +1,51 @@
+// TortoiseSVN - a Windows shell extension for easy version control\r
+\r
+// Copyright (C) 2003-2006 - Stefan Kueng\r
+\r
+// This program is free software; you can redistribute it and/or\r
+// modify it under the terms of the GNU General Public License\r
+// as published by the Free Software Foundation; either version 2\r
+// of the License, or (at your option) any later version.\r
+\r
+// This program is distributed in the hope that it will be useful,\r
+// but WITHOUT ANY WARRANTY; without even the implied warranty of\r
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\r
+// GNU General Public License for more details.\r
+\r
+// You should have received a copy of the GNU General Public License\r
+// along with this program; if not, write to the Free Software Foundation,\r
+// 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.\r
+//\r
+#pragma once\r
+\r
+\r
+/**\r
+ * \ingroup TortoiseShell\r
+ * This class factory object creates the main handlers -\r
+ * its constructor says which OLE class it has to make.\r
+ */\r
+class CShellExtClassFactory : public IClassFactory\r
+{\r
+protected:\r
+    ULONG m_cRef;\r
+    /// variable to contain class of object (i.e. not under source control, up to date)\r
+    FileState          m_StateToMake;\r
+\r
+       \r
+public:\r
+    CShellExtClassFactory(FileState state);\r
+    virtual ~CShellExtClassFactory();\r
+       \r
+       //@{\r
+    /// IUnknown members\r
+    STDMETHODIMP         QueryInterface(REFIID, LPVOID FAR *);\r
+    STDMETHODIMP_(ULONG) AddRef();\r
+    STDMETHODIMP_(ULONG) Release();\r
+       //@}\r
+    \r
+       //@{\r
+    /// IClassFactory members\r
+    STDMETHODIMP      CreateInstance(LPUNKNOWN, REFIID, LPVOID FAR *);\r
+    STDMETHODIMP      LockServer(BOOL);\r
+       //@}\r
+};\r
diff --git a/TortoiseShell/TortoiseSVN.cpp b/TortoiseShell/TortoiseSVN.cpp
new file mode 100644 (file)
index 0000000..295a91b
--- /dev/null
@@ -0,0 +1,169 @@
+// TortoiseSVN - a Windows shell extension for easy version control\r
+\r
+// Copyright (C) 2003-2008 - TortoiseSVN\r
+\r
+// This program is free software; you can redistribute it and/or\r
+// modify it under the terms of the GNU General Public License\r
+// as published by the Free Software Foundation; either version 2\r
+// of the License, or (at your option) any later version.\r
+\r
+// This program is distributed in the hope that it will be useful,\r
+// but WITHOUT ANY WARRANTY; without even the implied warranty of\r
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\r
+// GNU General Public License for more details.\r
+\r
+// You should have received a copy of the GNU General Public License\r
+// along with this program; if not, write to the Free Software Foundation,\r
+// 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.\r
+//\r
+#include "stdafx.h"\r
+#include "ShellExt.h"\r
+#include "Guids.h"\r
+#include "ShellExtClassFactory.h"\r
+#include "svn_dso.h"\r
+\r
+UINT                           g_cRefThisDll = 0;                              ///< reference count of this DLL.\r
+HINSTANCE                      g_hmodThisDll = NULL;                   ///< handle to this DLL itself.\r
+int                                    g_cAprInit = 0;\r
+ShellCache                     g_ShellCache;                                   ///< caching of registry entries, ...\r
+DWORD                          g_langid;\r
+DWORD                          g_langTimeout = 0;\r
+HINSTANCE                      g_hResInst = NULL;\r
+stdstring                      g_filepath;\r
+svn_wc_status_kind     g_filestatus = svn_wc_status_none;      ///< holds the corresponding status to the file/dir above\r
+bool                           g_readonlyoverlay = false;\r
+bool                           g_lockedoverlay = false;\r
+\r
+bool                           g_normalovlloaded = false;\r
+bool                           g_modifiedovlloaded = false;\r
+bool                           g_conflictedovlloaded = false;\r
+bool                           g_readonlyovlloaded = false;\r
+bool                           g_deletedovlloaded = false;\r
+bool                           g_lockedovlloaded = false;\r
+bool                           g_addedovlloaded = false;\r
+bool                           g_ignoredovlloaded = false;\r
+bool                           g_unversionedovlloaded = false;\r
+CComCriticalSection    g_csGlobalCOMGuard;\r
+\r
+LPCTSTR                                g_MenuIDString = _T("TortoiseSVN");\r
+extern std::set<CShellExt *> g_exts;\r
+\r
+#pragma comment(linker, "\"/manifestdependency:type='win32' name='Microsoft.Windows.Common-Controls' version='6.0.0.0' processorArchitecture='*' publicKeyToken='6595b64144ccf1df' language='*'\"")\r
+\r
+extern "C" int APIENTRY\r
+DllMain(HINSTANCE hInstance, DWORD dwReason, LPVOID /* lpReserved */)\r
+{\r
+#ifdef _DEBUG\r
+       // if no debugger is present, then don't load the dll.\r
+       // this prevents other apps from loading the dll and locking\r
+       // it.\r
+\r
+       bool bInShellTest = false;\r
+       TCHAR buf[_MAX_PATH + 1];               // MAX_PATH ok, the test really is for debugging anyway.\r
+       DWORD pathLength = GetModuleFileName(NULL, buf, _MAX_PATH);\r
+       if(pathLength >= 14)\r
+       {\r
+               if ((_tcsicmp(&buf[pathLength-14], _T("\\ShellTest.exe"))) == 0)\r
+               {\r
+                       bInShellTest = true;\r
+               }\r
+               if ((_tcsicmp(&buf[pathLength-13], _T("\\verclsid.exe"))) == 0)\r
+               {\r
+                       bInShellTest = true;\r
+               }\r
+       }\r
+\r
+       if (!::IsDebuggerPresent() && !bInShellTest)\r
+       {\r
+               ATLTRACE("In debug load preventer\n");\r
+               return FALSE;\r
+       }\r
+#endif\r
+\r
+       // NOTE: Do *NOT* call apr_initialize() or apr_terminate() here in DllMain(),\r
+       // because those functions call LoadLibrary() indirectly through malloc().\r
+       // And LoadLibrary() inside DllMain() is not allowed and can lead to unexpected\r
+       // behavior and even may create dependency loops in the dll load order.\r
+    if (dwReason == DLL_PROCESS_ATTACH)\r
+    {\r
+               if (g_hmodThisDll == NULL)\r
+               {\r
+                       g_csGlobalCOMGuard.Init();\r
+               }\r
+\r
+        // Extension DLL one-time initialization\r
+        g_hmodThisDll = hInstance;\r
+    }\r
+    else if (dwReason == DLL_PROCESS_DETACH)\r
+    {\r
+               // sometimes an application doesn't release all COM objects\r
+               // but still unloads the dll.\r
+               // in that case, we do it ourselves\r
+               if (g_cRefThisDll > 0)\r
+               {\r
+                       std::set<CShellExt *>::iterator it = g_exts.begin();\r
+                       while (it != g_exts.end())\r
+                       {\r
+                               delete *it;\r
+                               it = g_exts.begin();\r
+                       }\r
+                       while (g_cAprInit--)\r
+                       {\r
+                               g_SVNAdminDir.Close();\r
+                               apr_terminate();\r
+                       }\r
+               }\r
+               g_csGlobalCOMGuard.Term();\r
+    }\r
+    return 1;   // ok\r
+}\r
+\r
+STDAPI DllCanUnloadNow(void)\r
+{\r
+       return (g_cRefThisDll == 0 ? S_OK : S_FALSE);\r
+}\r
+\r
+STDAPI DllGetClassObject(REFCLSID rclsid, REFIID riid, LPVOID *ppvOut)\r
+{\r
+    *ppvOut = NULL;\r
+       \r
+    FileState state = FileStateInvalid;\r
+    if (IsEqualIID(rclsid, CLSID_TortoiseSVN_UPTODATE))\r
+        state = FileStateVersioned;\r
+    else if (IsEqualIID(rclsid, CLSID_TortoiseSVN_MODIFIED))\r
+        state = FileStateModified;\r
+    else if (IsEqualIID(rclsid, CLSID_TortoiseSVN_CONFLICTING))\r
+        state = FileStateConflict;\r
+    else if (IsEqualIID(rclsid, CLSID_TortoiseSVN_UNCONTROLLED))\r
+        state = FileStateUncontrolled;\r
+       else if (IsEqualIID(rclsid, CLSID_TortoiseSVN_DROPHANDLER))\r
+               state = FileStateDropHandler;\r
+       else if (IsEqualIID(rclsid, CLSID_TortoiseSVN_DELETED))\r
+               state = FileStateDeleted;\r
+       else if (IsEqualIID(rclsid, CLSID_TortoiseSVN_READONLY))\r
+               state = FileStateReadOnly;\r
+       else if (IsEqualIID(rclsid, CLSID_TortoiseSVN_LOCKED))\r
+               state = FileStateLockedOverlay;\r
+       else if (IsEqualIID(rclsid, CLSID_TortoiseSVN_ADDED))\r
+               state = FileStateAddedOverlay;\r
+       else if (IsEqualIID(rclsid, CLSID_TortoiseSVN_IGNORED))\r
+               state = FileStateIgnoredOverlay;\r
+       else if (IsEqualIID(rclsid, CLSID_TortoiseSVN_UNVERSIONED))\r
+               state = FileStateUnversionedOverlay;\r
+       \r
+    if (state != FileStateInvalid)\r
+    {\r
+               apr_initialize();\r
+               svn_dso_initialize2();\r
+               g_SVNAdminDir.Init();\r
+               g_cAprInit++;\r
+               \r
+               CShellExtClassFactory *pcf = new CShellExtClassFactory(state);\r
+               return pcf->QueryInterface(riid, ppvOut);\r
+    }\r
+       \r
+    return CLASS_E_CLASSNOTAVAILABLE;\r
+\r
+}\r
+\r
+\r
diff --git a/TortoiseShell/TortoiseShell.vcproj b/TortoiseShell/TortoiseShell.vcproj
new file mode 100644 (file)
index 0000000..88b5d6f
--- /dev/null
@@ -0,0 +1,869 @@
+<?xml version="1.0" encoding="Windows-1252"?>\r
+<VisualStudioProject\r
+       ProjectType="Visual C++"\r
+       Version="9.00"\r
+       Name="TortoiseShell"\r
+       ProjectGUID="{E873DD32-5A31-4DE1-8341-A56A2A5489EA}"\r
+       RootNamespace="TortoiseShell"\r
+       TargetFrameworkVersion="131072"\r
+       >\r
+       <Platforms>\r
+               <Platform\r
+                       Name="Win32"\r
+               />\r
+               <Platform\r
+                       Name="x64"\r
+               />\r
+       </Platforms>\r
+       <ToolFiles>\r
+       </ToolFiles>\r
+       <Configurations>\r
+               <Configuration\r
+                       Name="Debug|Win32"\r
+                       OutputDirectory="..\..\bin\Debug\bin"\r
+                       IntermediateDirectory="..\..\obj\TortoiseShell\Debug"\r
+                       ConfigurationType="2"\r
+                       UseOfMFC="0"\r
+                       UseOfATL="1"\r
+                       ATLMinimizesCRunTimeLibraryUsage="false"\r
+                       CharacterSet="1"\r
+                       >\r
+                       <Tool\r
+                               Name="VCPreBuildEventTool"\r
+                       />\r
+                       <Tool\r
+                               Name="VCCustomBuildTool"\r
+                       />\r
+                       <Tool\r
+                               Name="VCXMLDataGeneratorTool"\r
+                       />\r
+                       <Tool\r
+                               Name="VCWebServiceProxyGeneratorTool"\r
+                       />\r
+                       <Tool\r
+                               Name="VCMIDLTool"\r
+                               PreprocessorDefinitions="_DEBUG"\r
+                               MkTypLibCompatible="true"\r
+                               SuppressStartupBanner="true"\r
+                               TargetEnvironment="1"\r
+                               TypeLibraryName=".\Debug/TortoiseShell.tlb"\r
+                       />\r
+                       <Tool\r
+                               Name="VCCLCompilerTool"\r
+                               Optimization="0"\r
+                               InlineFunctionExpansion="0"\r
+                               AdditionalIncludeDirectories="&quot;../../ext/apr-util/include&quot;;&quot;../../ext/apr-util/xml/expat/lib&quot;;../../ext/Subversion/subversion/include;../../ext/apr/include;../Utils;..\TortoiseShell;..\SVN;&quot;..\..\ext\libintl\libintl3-win32\inc&quot;;..\Utils\MiscUI"\r
+                               PreprocessorDefinitions="WIN32;_DEBUG;_WINDOWS;_USRDLL;SVN_DEBUG"\r
+                               BasicRuntimeChecks="1"\r
+                               RuntimeLibrary="3"\r
+                               ForceConformanceInForLoopScope="true"\r
+                               RuntimeTypeInfo="true"\r
+                               UsePrecompiledHeader="2"\r
+                               AssemblerListingLocation="..\..\obj\TortoiseShell\Debug/"\r
+                               ObjectFile="..\..\obj\TortoiseShell\Debug/"\r
+                               ProgramDataBaseFileName="..\..\obj\TortoiseShell\Debug/"\r
+                               WarningLevel="4"\r
+                               SuppressStartupBanner="true"\r
+                               DebugInformationFormat="4"\r
+                               CompileAs="0"\r
+                       />\r
+                       <Tool\r
+                               Name="VCManagedResourceCompilerTool"\r
+                       />\r
+                       <Tool\r
+                               Name="VCResourceCompilerTool"\r
+                               PreprocessorDefinitions="_DEBUG;TSVNSHELL"\r
+                               Culture="1033"\r
+                       />\r
+                       <Tool\r
+                               Name="VCPreLinkEventTool"\r
+                       />\r
+                       <Tool\r
+                               Name="VCLinkerTool"\r
+                               IgnoreImportLibrary="true"\r
+                               AdditionalOptions="/MACHINE:I386"\r
+                               AdditionalDependencies="Crypt32.lib gdiplus.lib shfolder.lib shell32.lib comctl32.lib ws2_32.lib rpcrt4.lib shlwapi.lib wininet.lib version.lib ../../ext/Subversion\debug_win32\libsvn_diff-nonet.lib ../../ext/Subversion\debug_win32\libsvn_ra-nonet.lib ../../ext/Subversion\debug_win32\libsvn_wc-nonet.lib ../../ext/Subversion\debug_win32\\libsvn_subr-nonet.lib ../../ext/Subversion\debug_win32\libsvn_client-nonet.lib ../../ext/Subversion\debug_win32\libsvn_delta-nonet.lib ../../ext/apr\debug_win32\libapr_tsvn.lib ../../ext/apr-util\debug_win32\libaprutil_tsvn.lib ../../ext/apr-util\xml\expat\lib\debug_win32\xml.lib ../../ext/libintl/libintl3-win32/lib/intl3_tsvn.lib"\r
+                               OutputFile="$(OutDir)/TortoiseSVN.dll"\r
+                               LinkIncremental="0"\r
+                               SuppressStartupBanner="true"\r
+                               IgnoreAllDefaultLibraries="false"\r
+                               IgnoreDefaultLibraryNames="LIBC"\r
+                               ModuleDefinitionFile=".\ShellExt.def"\r
+                               DelayLoadDLLs="gdiplus.dll"\r
+                               GenerateDebugInformation="true"\r
+                               ProgramDatabaseFile="$(OutDir)/TortoiseSVN.pdb"\r
+                               BaseAddress="0x5960000"\r
+                               RandomizedBaseAddress="1"\r
+                               DataExecutionPrevention="0"\r
+                               ImportLibrary="..\..\obj\TortoiseShell\Debug/TortoiseSVN.lib"\r
+                               TargetMachine="1"\r
+                       />\r
+                       <Tool\r
+                               Name="VCALinkTool"\r
+                       />\r
+                       <Tool\r
+                               Name="VCManifestTool"\r
+                       />\r
+                       <Tool\r
+                               Name="VCXDCMakeTool"\r
+                       />\r
+                       <Tool\r
+                               Name="VCBscMakeTool"\r
+                       />\r
+                       <Tool\r
+                               Name="VCFxCopTool"\r
+                       />\r
+                       <Tool\r
+                               Name="VCAppVerifierTool"\r
+                       />\r
+                       <Tool\r
+                               Name="VCPostBuildEventTool"\r
+                       />\r
+               </Configuration>\r
+               <Configuration\r
+                       Name="Release|Win32"\r
+                       OutputDirectory="..\..\bin\Release\bin"\r
+                       IntermediateDirectory="..\..\obj\TortoiseShell\Release"\r
+                       ConfigurationType="2"\r
+                       UseOfMFC="0"\r
+                       UseOfATL="1"\r
+                       ATLMinimizesCRunTimeLibraryUsage="false"\r
+                       CharacterSet="1"\r
+                       WholeProgramOptimization="1"\r
+                       >\r
+                       <Tool\r
+                               Name="VCPreBuildEventTool"\r
+                       />\r
+                       <Tool\r
+                               Name="VCCustomBuildTool"\r
+                       />\r
+                       <Tool\r
+                               Name="VCXMLDataGeneratorTool"\r
+                       />\r
+                       <Tool\r
+                               Name="VCWebServiceProxyGeneratorTool"\r
+                       />\r
+                       <Tool\r
+                               Name="VCMIDLTool"\r
+                               PreprocessorDefinitions="NDEBUG"\r
+                               MkTypLibCompatible="true"\r
+                               SuppressStartupBanner="true"\r
+                               TargetEnvironment="1"\r
+                               TypeLibraryName=".\Release/TortoiseShell.tlb"\r
+                       />\r
+                       <Tool\r
+                               Name="VCCLCompilerTool"\r
+                               InlineFunctionExpansion="1"\r
+                               EnableIntrinsicFunctions="true"\r
+                               FavorSizeOrSpeed="1"\r
+                               OmitFramePointers="true"\r
+                               AdditionalIncludeDirectories="&quot;../../ext/apr-util/include&quot;;&quot;../../ext/apr-util/xml/expat/lib&quot;;../../ext/Subversion/subversion/include;../../ext/apr/include;..\TortoiseShell;..\Utils;..\svn;&quot;..\..\ext\libintl\libintl3-win32\inc&quot;;..\Utils\MiscUI"\r
+                               PreprocessorDefinitions="WIN32;NDEBUG;_WINDOWS;_USRDLL"\r
+                               StringPooling="true"\r
+                               RuntimeLibrary="2"\r
+                               BufferSecurityCheck="false"\r
+                               EnableFunctionLevelLinking="false"\r
+                               ForceConformanceInForLoopScope="true"\r
+                               UsePrecompiledHeader="2"\r
+                               AssemblerListingLocation="..\..\obj\TortoiseShell\Release/"\r
+                               ObjectFile="..\..\obj\TortoiseShell\Release/"\r
+                               ProgramDataBaseFileName="..\..\obj\TortoiseShell\Release/"\r
+                               WarningLevel="4"\r
+                               SuppressStartupBanner="true"\r
+                               CompileAs="0"\r
+                       />\r
+                       <Tool\r
+                               Name="VCManagedResourceCompilerTool"\r
+                       />\r
+                       <Tool\r
+                               Name="VCResourceCompilerTool"\r
+                               PreprocessorDefinitions="NDEBUG;TSVNSHELL"\r
+                               Culture="1033"\r
+                       />\r
+                       <Tool\r
+                               Name="VCPreLinkEventTool"\r
+                       />\r
+                       <Tool\r
+                               Name="VCLinkerTool"\r
+                               IgnoreImportLibrary="true"\r
+                               AdditionalOptions="/MACHINE:I386"\r
+                               AdditionalDependencies="Crypt32.lib gdiplus.lib shfolder.lib shell32.lib comctl32.lib ws2_32.lib rpcrt4.lib shlwapi.lib wininet.lib version.lib"\r
+                               OutputFile="$(OutDir)/TortoiseSVN.dll"\r
+                               LinkIncremental="1"\r
+                               SuppressStartupBanner="true"\r
+                               IgnoreDefaultLibraryNames="libcd, libc, shell32"\r
+                               ModuleDefinitionFile=".\ShellExt.def"\r
+                               DelayLoadDLLs="gdiplus.dll"\r
+                               GenerateDebugInformation="true"\r
+                               ProgramDatabaseFile="$(OutDir)/TortoiseShell.pdb"\r
+                               SubSystem="2"\r
+                               OptimizeReferences="2"\r
+                               EnableCOMDATFolding="2"\r
+                               OptimizeForWindows98="0"\r
+                               BaseAddress="0x5960000"\r
+                               RandomizedBaseAddress="1"\r
+                               DataExecutionPrevention="0"\r
+                               ImportLibrary="..\..\obj\TortoiseShell\Release/TortoiseSVN.lib"\r
+                               TargetMachine="1"\r
+                       />\r
+                       <Tool\r
+                               Name="VCALinkTool"\r
+                       />\r
+                       <Tool\r
+                               Name="VCManifestTool"\r
+                       />\r
+                       <Tool\r
+                               Name="VCXDCMakeTool"\r
+                       />\r
+                       <Tool\r
+                               Name="VCBscMakeTool"\r
+                       />\r
+                       <Tool\r
+                               Name="VCFxCopTool"\r
+                       />\r
+                       <Tool\r
+                               Name="VCAppVerifierTool"\r
+                       />\r
+                       <Tool\r
+                               Name="VCPostBuildEventTool"\r
+                       />\r
+               </Configuration>\r
+               <Configuration\r
+                       Name="Debug|x64"\r
+                       OutputDirectory="..\..\bin\Debug64\bin"\r
+                       IntermediateDirectory="..\..\obj\TortoiseShell\Debug64"\r
+                       ConfigurationType="2"\r
+                       UseOfMFC="0"\r
+                       UseOfATL="1"\r
+                       ATLMinimizesCRunTimeLibraryUsage="false"\r
+                       CharacterSet="1"\r
+                       >\r
+                       <Tool\r
+                               Name="VCPreBuildEventTool"\r
+                       />\r
+                       <Tool\r
+                               Name="VCCustomBuildTool"\r
+                       />\r
+                       <Tool\r
+                               Name="VCXMLDataGeneratorTool"\r
+                       />\r
+                       <Tool\r
+                               Name="VCWebServiceProxyGeneratorTool"\r
+                       />\r
+                       <Tool\r
+                               Name="VCMIDLTool"\r
+                               PreprocessorDefinitions="_DEBUG"\r
+                               MkTypLibCompatible="true"\r
+                               SuppressStartupBanner="true"\r
+                               TargetEnvironment="3"\r
+                               TypeLibraryName=".\Debug/TortoiseShell.tlb"\r
+                       />\r
+                       <Tool\r
+                               Name="VCCLCompilerTool"\r
+                               Optimization="0"\r
+                               InlineFunctionExpansion="0"\r
+                               AdditionalIncludeDirectories="&quot;../../ext/apr-util/include&quot;;&quot;../../ext/apr-util/xml/expat/lib&quot;;../../ext/Subversion/subversion/include;../../ext/apr/include;../Utils;..\TortoiseShell;..\SVN;&quot;..\..\ext\libintl\libintl3-x64\inc&quot;;..\Utils\MiscUI"\r
+                               PreprocessorDefinitions="WIN64;_DEBUG;_WINDOWS;_USRDLL;SVN_DEBUG"\r
+                               BasicRuntimeChecks="1"\r
+                               RuntimeLibrary="3"\r
+                               ForceConformanceInForLoopScope="true"\r
+                               RuntimeTypeInfo="true"\r
+                               UsePrecompiledHeader="2"\r
+                               AssemblerListingLocation="..\..\obj\TortoiseShell\Debug64/"\r
+                               ObjectFile="..\..\obj\TortoiseShell\Debug64/"\r
+                               ProgramDataBaseFileName="..\..\obj\TortoiseShell\Debug64/"\r
+                               WarningLevel="4"\r
+                               SuppressStartupBanner="true"\r
+                               DebugInformationFormat="3"\r
+                               CompileAs="0"\r
+                       />\r
+                       <Tool\r
+                               Name="VCManagedResourceCompilerTool"\r
+                       />\r
+                       <Tool\r
+                               Name="VCResourceCompilerTool"\r
+                               PreprocessorDefinitions="_DEBUG;TSVNSHELL"\r
+                               Culture="1033"\r
+                       />\r
+                       <Tool\r
+                               Name="VCPreLinkEventTool"\r
+                       />\r
+                       <Tool\r
+                               Name="VCLinkerTool"\r
+                               IgnoreImportLibrary="true"\r
+                               AdditionalDependencies="Crypt32.lib gdiplus.lib shfolder.lib shell32.lib comctl32.lib ws2_32.lib rpcrt4.lib shlwapi.lib wininet.lib version.lib ../../ext/Subversion\debug_x64\libsvn_diff-nonet.lib ../../ext/Subversion\debug_x64\libsvn_ra-nonet.lib ../../ext/Subversion\debug_x64\libsvn_wc-nonet.lib ../../ext/Subversion\debug_x64\\libsvn_subr-nonet.lib ../../ext/Subversion\debug_x64\libsvn_client-nonet.lib ../../ext/Subversion\debug_x64\libsvn_delta-nonet.lib ../../ext/apr\debug_x64\libapr_tsvn.lib ../../ext/apr-util\debug_x64\libaprutil_tsvn.lib ../../ext/apr-util\xml\expat\lib\debug_x64\xml.lib ../../ext/libintl/libintl3-x64/lib/intl3_tsvn.lib"\r
+                               OutputFile="$(OutDir)/TortoiseSVN.dll"\r
+                               LinkIncremental="0"\r
+                               SuppressStartupBanner="true"\r
+                               IgnoreAllDefaultLibraries="false"\r
+                               IgnoreDefaultLibraryNames="LIBC"\r
+                               ModuleDefinitionFile=".\ShellExt.def"\r
+                               DelayLoadDLLs="gdiplus.dll"\r
+                               GenerateDebugInformation="true"\r
+                               ProgramDatabaseFile="$(OutDir)/TortoiseSVN.pdb"\r
+                               BaseAddress="0x5960000"\r
+                               RandomizedBaseAddress="1"\r
+                               DataExecutionPrevention="0"\r
+                               ImportLibrary="..\..\obj\TortoiseShell\Debug64/TortoiseSVN.lib"\r
+                               TargetMachine="17"\r
+                       />\r
+                       <Tool\r
+                               Name="VCALinkTool"\r
+                       />\r
+                       <Tool\r
+                               Name="VCManifestTool"\r
+                       />\r
+                       <Tool\r
+                               Name="VCXDCMakeTool"\r
+                       />\r
+                       <Tool\r
+                               Name="VCBscMakeTool"\r
+                       />\r
+                       <Tool\r
+                               Name="VCFxCopTool"\r
+                       />\r
+                       <Tool\r
+                               Name="VCAppVerifierTool"\r
+                       />\r
+                       <Tool\r
+                               Name="VCPostBuildEventTool"\r
+                       />\r
+               </Configuration>\r
+               <Configuration\r
+                       Name="Release|x64"\r
+                       OutputDirectory="..\..\bin\Release64\bin"\r
+                       IntermediateDirectory="..\..\obj\TortoiseShell\Release64"\r
+                       ConfigurationType="2"\r
+                       UseOfMFC="0"\r
+                       UseOfATL="1"\r
+                       ATLMinimizesCRunTimeLibraryUsage="false"\r
+                       CharacterSet="1"\r
+                       WholeProgramOptimization="1"\r
+                       >\r
+                       <Tool\r
+                               Name="VCPreBuildEventTool"\r
+                       />\r
+                       <Tool\r
+                               Name="VCCustomBuildTool"\r
+                       />\r
+                       <Tool\r
+                               Name="VCXMLDataGeneratorTool"\r
+                       />\r
+                       <Tool\r
+                               Name="VCWebServiceProxyGeneratorTool"\r
+                       />\r
+                       <Tool\r
+                               Name="VCMIDLTool"\r
+                               PreprocessorDefinitions="NDEBUG"\r
+                               MkTypLibCompatible="true"\r
+                               SuppressStartupBanner="true"\r
+                               TargetEnvironment="3"\r
+                               TypeLibraryName=".\Release/TortoiseShell.tlb"\r
+                       />\r
+                       <Tool\r
+                               Name="VCCLCompilerTool"\r
+                               InlineFunctionExpansion="1"\r
+                               EnableIntrinsicFunctions="true"\r
+                               FavorSizeOrSpeed="1"\r
+                               OmitFramePointers="true"\r
+                               AdditionalIncludeDirectories="&quot;../../ext/apr-util/include&quot;;&quot;../../ext/apr-util/xml/expat/lib&quot;;../../ext/Subversion/subversion/include;../../ext/apr/include;..\TortoiseShell;..\Utils;..\svn;&quot;..\..\ext\libintl\libintl3-x64\inc&quot;;..\Utils\MiscUI"\r
+                               PreprocessorDefinitions="WIN64;NDEBUG;_WINDOWS;_USRDLL"\r
+                               StringPooling="true"\r
+                               RuntimeLibrary="2"\r
+                               BufferSecurityCheck="false"\r
+                               EnableFunctionLevelLinking="false"\r
+                               ForceConformanceInForLoopScope="true"\r
+                               UsePrecompiledHeader="2"\r
+                               AssemblerListingLocation="..\..\obj\TortoiseShell\Release64/"\r
+                               ObjectFile="..\..\obj\TortoiseShell\Release64/"\r
+                               ProgramDataBaseFileName="..\..\obj\TortoiseShell\Release64/"\r
+                               WarningLevel="4"\r
+                               SuppressStartupBanner="true"\r
+                               CompileAs="2"\r
+                       />\r
+                       <Tool\r
+                               Name="VCManagedResourceCompilerTool"\r
+                       />\r
+                       <Tool\r
+                               Name="VCResourceCompilerTool"\r
+                               PreprocessorDefinitions="NDEBUG;TSVNSHELL"\r
+                               Culture="1033"\r
+                       />\r
+                       <Tool\r
+                               Name="VCPreLinkEventTool"\r
+                       />\r
+                       <Tool\r
+                               Name="VCLinkerTool"\r
+                               IgnoreImportLibrary="true"\r
+                               AdditionalDependencies="Crypt32.lib gdiplus.lib shfolder.lib shell32.lib comctl32.lib ws2_32.lib rpcrt4.lib shlwapi.lib wininet.lib version.lib ../../ext/Subversion\release_x64\libsvn_diff-nonet.lib ../../ext/Subversion\release_x64\libsvn_delta-nonet.lib ../../ext/Subversion\release_x64\\libsvn_wc-nonet.lib ../../ext/Subversion\release_x64\\libsvn_subr-nonet.lib ../../ext/Subversion\release_x64\libsvn_client-nonet.lib ../../ext/Subversion\release_x64\libsvn_ra-nonet.lib ../../ext/apr\release_x64\libapr_tsvn.lib ../../ext/apr-util\release_x64\libaprutil_tsvn.lib ../../ext/apr-util\xml\expat\lib\release_x64\xml.lib ../../ext/libintl/libintl3-x64/lib/intl3_tsvn.lib"\r
+                               OutputFile="$(OutDir)/TortoiseSVN.dll"\r
+                               LinkIncremental="1"\r
+                               SuppressStartupBanner="true"\r
+                               IgnoreDefaultLibraryNames="libcd, libc, shell32"\r
+                               ModuleDefinitionFile=".\ShellExt.def"\r
+                               DelayLoadDLLs="gdiplus.dll"\r
+                               GenerateDebugInformation="true"\r
+                               ProgramDatabaseFile="$(OutDir)/TortoiseShell.pdb"\r
+                               SubSystem="2"\r
+                               OptimizeReferences="2"\r
+                               EnableCOMDATFolding="2"\r
+                               OptimizeForWindows98="1"\r
+                               BaseAddress="0x5960000"\r
+                               RandomizedBaseAddress="1"\r
+                               DataExecutionPrevention="0"\r
+                               ImportLibrary="..\..\obj\TortoiseShell\Release64/TortoiseSVN.lib"\r
+                               TargetMachine="17"\r
+                       />\r
+                       <Tool\r
+                               Name="VCALinkTool"\r
+                       />\r
+                       <Tool\r
+                               Name="VCManifestTool"\r
+                       />\r
+                       <Tool\r
+                               Name="VCXDCMakeTool"\r
+                       />\r
+                       <Tool\r
+                               Name="VCBscMakeTool"\r
+                       />\r
+                       <Tool\r
+                               Name="VCFxCopTool"\r
+                       />\r
+                       <Tool\r
+                               Name="VCAppVerifierTool"\r
+                       />\r
+                       <Tool\r
+                               Name="VCPostBuildEventTool"\r
+                       />\r
+               </Configuration>\r
+       </Configurations>\r
+       <References>\r
+       </References>\r
+       <Files>\r
+               <Filter\r
+                       Name="Source Files"\r
+                       Filter="cpp;c;cxx;def;odl;idl;hpj;bat;asm"\r
+                       >\r
+                       <File\r
+                               RelativePath="..\TSVNCache\CacheInterface.cpp"\r
+                               >\r
+                       </File>\r
+                       <File\r
+                               RelativePath="ColumnProvider.cpp"\r
+                               >\r
+                       </File>\r
+                       <File\r
+                               RelativePath=".\ContextMenu.cpp"\r
+                               >\r
+                       </File>\r
+                       <File\r
+                               RelativePath=".\IconOverlay.cpp"\r
+                               >\r
+                       </File>\r
+                       <File\r
+                               RelativePath=".\ItemIDList.cpp"\r
+                               >\r
+                       </File>\r
+                       <File\r
+                               RelativePath="..\Utils\PathUtils.cpp"\r
+                               >\r
+                       </File>\r
+                       <File\r
+                               RelativePath=".\PIDL.cpp"\r
+                               >\r
+                       </File>\r
+                       <File\r
+                               RelativePath="PreserveChdir.cpp"\r
+                               >\r
+                       </File>\r
+                       <File\r
+                               RelativePath="..\Utils\Registry.cpp"\r
+                               >\r
+                       </File>\r
+                       <File\r
+                               RelativePath=".\RemoteCacheLink.cpp"\r
+                               >\r
+                       </File>\r
+                       <File\r
+                               RelativePath=".\ShellExt.cpp"\r
+                               >\r
+                       </File>\r
+                       <File\r
+                               RelativePath=".\ShellExt.def"\r
+                               >\r
+                       </File>\r
+                       <File\r
+                               RelativePath=".\ShellExtClassFactory.cpp"\r
+                               >\r
+                       </File>\r
+                       <File\r
+                               RelativePath="stdafx.cpp"\r
+                               >\r
+                               <FileConfiguration\r
+                                       Name="Debug|Win32"\r
+                                       >\r
+                                       <Tool\r
+                                               Name="VCCLCompilerTool"\r
+                                               UsePrecompiledHeader="1"\r
+                                       />\r
+                               </FileConfiguration>\r
+                               <FileConfiguration\r
+                                       Name="Release|Win32"\r
+                                       >\r
+                                       <Tool\r
+                                               Name="VCCLCompilerTool"\r
+                                               UsePrecompiledHeader="1"\r
+                                       />\r
+                               </FileConfiguration>\r
+                               <FileConfiguration\r
+                                       Name="Debug|x64"\r
+                                       >\r
+                                       <Tool\r
+                                               Name="VCCLCompilerTool"\r
+                                               UsePrecompiledHeader="1"\r
+                                       />\r
+                               </FileConfiguration>\r
+                               <FileConfiguration\r
+                                       Name="Release|x64"\r
+                                       >\r
+                                       <Tool\r
+                                               Name="VCCLCompilerTool"\r
+                                               UsePrecompiledHeader="1"\r
+                                       />\r
+                               </FileConfiguration>\r
+                       </File>\r
+                       <File\r
+                               RelativePath="..\Svn\SVNAdminDir.cpp"\r
+                               >\r
+                       </File>\r
+                       <File\r
+                               RelativePath="..\SVN\SVNFolderStatus.cpp"\r
+                               >\r
+                       </File>\r
+                       <File\r
+                               RelativePath="..\SVN\SVNGlobal.cpp"\r
+                               >\r
+                       </File>\r
+                       <File\r
+                               RelativePath="..\Svn\SVNHelpers.cpp"\r
+                               >\r
+                       </File>\r
+                       <File\r
+                               RelativePath="..\SVN\SVNProperties.cpp"\r
+                               >\r
+                       </File>\r
+                       <File\r
+                               RelativePath="SVNPropertyPage.cpp"\r
+                               >\r
+                       </File>\r
+                       <File\r
+                               RelativePath="..\SVN\SVNRev.cpp"\r
+                               >\r
+                       </File>\r
+                       <File\r
+                               RelativePath="..\SVN\SVNStatus.cpp"\r
+                               >\r
+                       </File>\r
+                       <File\r
+                               RelativePath=".\TortoiseSVN.cpp"\r
+                               >\r
+                       </File>\r
+                       <File\r
+                               RelativePath="..\Svn\TSVNPath.cpp"\r
+                               >\r
+                       </File>\r
+                       <File\r
+                               RelativePath="..\Utils\UnicodeUtils.cpp"\r
+                               >\r
+                       </File>\r
+               </Filter>\r
+               <Filter\r
+                       Name="Header Files"\r
+                       Filter="h;hpp;hxx;hm;inl;inc"\r
+                       >\r
+                       <File\r
+                               RelativePath=".\Globals.h"\r
+                               >\r
+                       </File>\r
+                       <File\r
+                               RelativePath=".\Guids.h"\r
+                               >\r
+                       </File>\r
+                       <File\r
+                               RelativePath=".\ItemIDList.h"\r
+                               >\r
+                       </File>\r
+                       <File\r
+                               RelativePath="..\Utils\PathUtils.h"\r
+                               >\r
+                       </File>\r
+                       <File\r
+                               RelativePath=".\PIDL.h"\r
+                               >\r
+                       </File>\r
+                       <File\r
+                               RelativePath="PreserveChdir.h"\r
+                               >\r
+                       </File>\r
+                       <File\r
+                               RelativePath="..\Utils\MiscUI\ProgressDlg.h"\r
+                               >\r
+                       </File>\r
+                       <File\r
+                               RelativePath="..\Utils\registry.h"\r
+                               >\r
+                       </File>\r
+                       <File\r
+                               RelativePath=".\RemoteCacheLink.h"\r
+                               >\r
+                       </File>\r
+                       <File\r
+                               RelativePath=".\resource.h"\r
+                               >\r
+                       </File>\r
+                       <File\r
+                               RelativePath=".\ShellCache.h"\r
+                               >\r
+                       </File>\r
+                       <File\r
+                               RelativePath=".\ShellExt.h"\r
+                               >\r
+                       </File>\r
+                       <File\r
+                               RelativePath=".\ShellExtClassFactory.h"\r
+                               >\r
+                       </File>\r
+                       <File\r
+                               RelativePath="stdafx.h"\r
+                               >\r
+                       </File>\r
+                       <File\r
+                               RelativePath="..\Svn\SVNAdminDir.h"\r
+                               >\r
+                       </File>\r
+                       <File\r
+                               RelativePath="..\SVN\SVNFolderStatus.h"\r
+                               >\r
+                       </File>\r
+                       <File\r
+                               RelativePath="..\SVN\SVNGlobal.h"\r
+                               >\r
+                       </File>\r
+                       <File\r
+                               RelativePath="..\Svn\SVNHelpers.h"\r
+                               >\r
+                       </File>\r
+                       <File\r
+                               RelativePath="..\SVN\SVNProperties.h"\r
+                               >\r
+                       </File>\r
+                       <File\r
+                               RelativePath="SVNPropertyPage.h"\r
+                               >\r
+                       </File>\r
+                       <File\r
+                               RelativePath="..\SVN\SVNRev.h"\r
+                               >\r
+                       </File>\r
+                       <File\r
+                               RelativePath="..\SVN\SVNStatus.h"\r
+                               >\r
+                       </File>\r
+                       <File\r
+                               RelativePath="..\Svn\TSVNPath.h"\r
+                               >\r
+                       </File>\r
+                       <File\r
+                               RelativePath="..\Utils\UnicodeUtils.h"\r
+                               >\r
+                       </File>\r
+               </Filter>\r
+               <Filter\r
+                       Name="Resource Files"\r
+                       Filter="rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;jpg;jpeg;jpe;manifest"\r
+                       >\r
+                       <File\r
+                               RelativePath="..\Resources\clipcopy.ico"\r
+                               >\r
+                       </File>\r
+                       <File\r
+                               RelativePath="..\Resources\clipcut.ico"\r
+                               >\r
+                       </File>\r
+                       <File\r
+                               RelativePath="..\Resources\clippaste.ico"\r
+                               >\r
+                       </File>\r
+                       <File\r
+                               RelativePath="..\Resources\menuabout.ico"\r
+                               >\r
+                       </File>\r
+                       <File\r
+                               RelativePath="..\Resources\menuadd.ico"\r
+                               >\r
+                       </File>\r
+                       <File\r
+                               RelativePath="..\Resources\menublame.ico"\r
+                               >\r
+                       </File>\r
+                       <File\r
+                               RelativePath="..\Resources\menucheckout.ico"\r
+                               >\r
+                       </File>\r
+                       <File\r
+                               RelativePath="..\Resources\menucleanup.ico"\r
+                               >\r
+                       </File>\r
+                       <File\r
+                               RelativePath="..\Resources\menucommit.ico"\r
+                               >\r
+                       </File>\r
+                       <File\r
+                               RelativePath="..\Resources\menucompare.ico"\r
+                               >\r
+                       </File>\r
+                       <File\r
+                               RelativePath="..\Resources\menuconflict.ico"\r
+                               >\r
+                       </File>\r
+                       <File\r
+                               RelativePath="..\Resources\menucopy.ico"\r
+                               >\r
+                       </File>\r
+                       <File\r
+                               RelativePath="..\Resources\menucreaterepos.ico"\r
+                               >\r
+                       </File>\r
+                       <File\r
+                               RelativePath="..\Resources\menudelete.ico"\r
+                               >\r
+                       </File>\r
+                       <File\r
+                               RelativePath="..\Resources\menudelunversioned.ico"\r
+                               >\r
+                       </File>\r
+                       <File\r
+                               RelativePath="..\Resources\menudiff.ico"\r
+                               >\r
+                       </File>\r
+                       <File\r
+                               RelativePath="..\Resources\menuexport.ico"\r
+                               >\r
+                       </File>\r
+                       <File\r
+                               RelativePath="..\Resources\menuhelp.ico"\r
+                               >\r
+                       </File>\r
+                       <File\r
+                               RelativePath="..\Resources\menuignore.ico"\r
+                               >\r
+                       </File>\r
+                       <File\r
+                               RelativePath="..\Resources\menuimport.ico"\r
+                               >\r
+                       </File>\r
+                       <File\r
+                               RelativePath="..\Resources\menulock.ico"\r
+                               >\r
+                       </File>\r
+                       <File\r
+                               RelativePath="..\Resources\menulog.ico"\r
+                               >\r
+                       </File>\r
+                       <File\r
+                               RelativePath="..\Resources\menumerge.ico"\r
+                               >\r
+                       </File>\r
+                       <File\r
+                               RelativePath="..\Resources\menupatch.ico"\r
+                               >\r
+                       </File>\r
+                       <File\r
+                               RelativePath="..\Resources\menuproperties.ico"\r
+                               >\r
+                       </File>\r
+                       <File\r
+                               RelativePath="..\Resources\menurelocate.ico"\r
+                               >\r
+                       </File>\r
+                       <File\r
+                               RelativePath="..\Resources\menurename.ico"\r
+                               >\r
+                       </File>\r
+                       <File\r
+                               RelativePath="..\Resources\menurepobrowse.ico"\r
+                               >\r
+                       </File>\r
+                       <File\r
+                               RelativePath="..\Resources\menuresolve.ico"\r
+                               >\r
+                       </File>\r
+                       <File\r
+                               RelativePath="..\Resources\menurevert.ico"\r
+                               >\r
+                       </File>\r
+                       <File\r
+                               RelativePath="..\Resources\menurevisiongraph.ico"\r
+                               >\r
+                       </File>\r
+                       <File\r
+                               RelativePath="..\Resources\menusettings.ico"\r
+                               >\r
+                       </File>\r
+                       <File\r
+                               RelativePath="..\Resources\menushowchanged.ico"\r
+                               >\r
+                       </File>\r
+                       <File\r
+                               RelativePath="..\Resources\menuswitch.ico"\r
+                               >\r
+                       </File>\r
+                       <File\r
+                               RelativePath="..\Resources\menuunlock.ico"\r
+                               >\r
+                       </File>\r
+                       <File\r
+                               RelativePath="..\Resources\menuupdate.ico"\r
+                               >\r
+                       </File>\r
+                       <File\r
+                               RelativePath=".\resource.rc"\r
+                               >\r
+                       </File>\r
+                       <File\r
+                               RelativePath=".\resource.rc2"\r
+                               >\r
+                       </File>\r
+                       <File\r
+                               RelativePath="..\Resources\Tortoise.ico"\r
+                               >\r
+                       </File>\r
+                       <File\r
+                               RelativePath="..\Resources\TortoiseSmall.ico"\r
+                               >\r
+                       </File>\r
+                       <File\r
+                               RelativePath="..\Resources\tsvnmenufile.ico"\r
+                               >\r
+                       </File>\r
+                       <File\r
+                               RelativePath="..\Resources\tsvnmenufolder.ico"\r
+                               >\r
+                       </File>\r
+                       <File\r
+                               RelativePath="..\Resources\tsvnmenulink.ico"\r
+                               >\r
+                       </File>\r
+                       <File\r
+                               RelativePath="..\Resources\tsvnmenumultiple.ico"\r
+                               >\r
+                       </File>\r
+               </Filter>\r
+       </Files>\r
+       <Globals>\r
+               <Global\r
+                       Name="DevPartner_IsInstrumented"\r
+                       Value="0"\r
+               />\r
+       </Globals>\r
+</VisualStudioProject>\r
diff --git a/TortoiseShell/TortoiseStub.c b/TortoiseShell/TortoiseStub.c
new file mode 100644 (file)
index 0000000..57bdba0
--- /dev/null
@@ -0,0 +1,271 @@
+// TortoiseSVN - a Windows shell extension for easy version control\r
+\r
+// Copyright (C) 2007 - TortoiseSVN\r
+\r
+// This program is free software; you can redistribute it and/or\r
+// modify it under the terms of the GNU General Public License\r
+// as published by the Free Software Foundation; either version 2\r
+// of the License, or (at your option) any later version.\r
+\r
+// This program is distributed in the hope that it will be useful,\r
+// but WITHOUT ANY WARRANTY; without even the implied warranty of\r
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\r
+// GNU General Public License for more details.\r
+\r
+// You should have received a copy of the GNU General Public License\r
+// along with this program; if not, write to the Free Software Foundation,\r
+// 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.\r
+//\r
+#define _WIN32_WINNT 0x0400\r
+#include <Windows.h>\r
+#include <tchar.h>\r
+#include "Debug.h"\r
+\r
+\r
+const HINSTANCE NIL = (HINSTANCE)((char*)(0)-1);\r
+\r
+static HINSTANCE hInst = NULL;\r
+\r
+static HINSTANCE hTortoiseSVN = NULL;\r
+static LPFNGETCLASSOBJECT pDllGetClassObject = NULL;\r
+static LPFNCANUNLOADNOW pDllCanUnloadNow = NULL;\r
+\r
+\r
+\r
+\r
+/**\r
+ * \ingroup TortoiseShell\r
+ * Check whether to load the full TortoiseSVN.dll or not.\r
+ */\r
+static BOOL WantRealVersion(void)\r
+{\r
+       static const WCHAR TSVNRootKey[]=_T("Software\\TortoiseSVN");\r
+       static const WCHAR ExplorerOnlyValue[]=_T("LoadDllOnlyInExplorer");\r
+\r
+       static const WCHAR ExplorerEnvPath[]=_T("%SystemRoot%\\explorer.exe");\r
+\r
+\r
+       DWORD bExplorerOnly = 0;\r
+       WCHAR ModuleName[MAX_PATH] = {0};\r
+       WCHAR ExplorerPath[MAX_PATH] = {0};\r
+\r
+       HKEY hKey = HKEY_CURRENT_USER;\r
+       LONG Result = ERROR;\r
+       DWORD Type = REG_DWORD;\r
+       DWORD Len = sizeof(DWORD);\r
+\r
+       BOOL bWantReal = TRUE;\r
+\r
+\r
+       TRACE(_T("WantRealVersion() - Enter\n"));\r
+\r
+       Result = RegOpenKeyEx(HKEY_CURRENT_USER, TSVNRootKey, 0, KEY_READ, &hKey);\r
+       if (Result == ERROR_SUCCESS)\r
+       {\r
+               Result = RegQueryValueEx(hKey, ExplorerOnlyValue, NULL, &Type, (BYTE *)&bExplorerOnly, &Len);\r
+               if ((Result == ERROR_SUCCESS) && (Type == REG_DWORD) && (Len == sizeof(DWORD)) && bExplorerOnly)\r
+               {\r
+                       TRACE(_T("WantRealVersion() - Explorer Only\n"));\r
+\r
+                       // check if the current process is in fact the explorer\r
+                       Len = GetModuleFileName(NULL, ModuleName, sizeof(ModuleName));\r
+                       if (Len)\r
+                       {\r
+                               TRACE(_T("Process is %s\n"), ModuleName);\r
+\r
+                               Len = ExpandEnvironmentStrings(ExplorerEnvPath, ExplorerPath, sizeof(ExplorerPath));\r
+                               if (Len && (Len <= sizeof(ExplorerPath)))\r
+                               {\r
+                                       TRACE(_T("Explorer path is %s\n"), ExplorerPath);\r
+                                       bWantReal = !lstrcmpi(ModuleName, ExplorerPath);\r
+                               }\r
+                       }\r
+               }\r
+\r
+               RegCloseKey(hKey);\r
+       }\r
+\r
+       TRACE(_T("WantRealVersion() - Exit\n"));\r
+       return bWantReal;\r
+}\r
+\r
+static void LoadRealLibrary(void)\r
+{\r
+       static const char GetClassObject[] = "DllGetClassObject";\r
+       static const char CanUnloadNow[] = "DllCanUnloadNow";\r
+\r
+       WCHAR ModuleName[MAX_PATH] = {0};\r
+       DWORD Len = 0;\r
+\r
+\r
+       if (hTortoiseSVN)\r
+               return;\r
+\r
+       if (!WantRealVersion())\r
+       {\r
+               TRACE(_T("LoadRealLibrary() - Bypass\n"));\r
+               hTortoiseSVN = NIL;\r
+               return;\r
+       }\r
+\r
+       Len = GetModuleFileName(hInst, ModuleName, sizeof(ModuleName));\r
+       if (!Len)\r
+       {\r
+               TRACE(_T("LoadRealLibrary() - Fail\n"));\r
+               hTortoiseSVN = NIL;\r
+               return;\r
+       }\r
+\r
+       // truncate the string at the last '\' char\r
+       while(Len > 0)\r
+       {\r
+               --Len;\r
+               if (ModuleName[Len] == '\\')\r
+               {\r
+                       ModuleName[Len] = '\0';\r
+                       break;\r
+               }\r
+       }\r
+       if (Len == 0)\r
+       {\r
+               TRACE(_T("LoadRealLibrary() - Fail\n"));\r
+               hTortoiseSVN = NIL;\r
+               return;\r
+       }\r
+       lstrcat(ModuleName, _T("\\TortoiseSVN.dll"));\r
+\r
+       TRACE(_T("LoadRealLibrary() - Load %s\n"), ModuleName);\r
+\r
+       hTortoiseSVN = LoadLibraryEx(ModuleName, NULL, LOAD_WITH_ALTERED_SEARCH_PATH);\r
+       if (!hTortoiseSVN)\r
+       {\r
+               TRACE(_T("LoadRealLibrary() - Fail\n"));\r
+               hTortoiseSVN = NIL;\r
+               return;\r
+       }\r
+\r
+       TRACE(_T("LoadRealLibrary() - Success\n"));\r
+       pDllGetClassObject = NULL;\r
+       pDllCanUnloadNow = NULL;\r
+       pDllGetClassObject = (LPFNGETCLASSOBJECT)GetProcAddress(hTortoiseSVN, GetClassObject);\r
+       if (pDllGetClassObject == NULL)\r
+       {\r
+               TRACE(_T("LoadRealLibrary() - Fail\n"));\r
+               FreeLibrary(hTortoiseSVN);\r
+               hTortoiseSVN = NIL;\r
+               return;\r
+       }\r
+       pDllCanUnloadNow = (LPFNCANUNLOADNOW)GetProcAddress(hTortoiseSVN, CanUnloadNow);\r
+       if (pDllCanUnloadNow == NULL)\r
+       {\r
+               TRACE(_T("LoadRealLibrary() - Fail\n"));\r
+               FreeLibrary(hTortoiseSVN);\r
+               hTortoiseSVN = NIL;\r
+               return;\r
+       }\r
+}\r
+\r
+static void UnloadRealLibrary(void)\r
+{\r
+       if (!hTortoiseSVN)\r
+               return;\r
+\r
+       if (hTortoiseSVN != NIL)\r
+               FreeLibrary(hTortoiseSVN);\r
+\r
+       hTortoiseSVN = NULL;\r
+       pDllGetClassObject = NULL;\r
+       pDllCanUnloadNow = NULL;\r
+}\r
+\r
+\r
+BOOL WINAPI DllMain(HINSTANCE hInstance, DWORD Reason, LPVOID Reserved)\r
+{\r
+#ifdef _DEBUG\r
+       // if no debugger is present, then don't load the dll.\r
+       // this prevents other apps from loading the dll and locking\r
+       // it.\r
+\r
+       BOOL bInShellTest = FALSE;\r
+       TCHAR buf[_MAX_PATH + 1];               // MAX_PATH ok, the test really is for debugging anyway.\r
+       DWORD pathLength = GetModuleFileName(NULL, buf, _MAX_PATH);\r
+\r
+       UNREFERENCED_PARAMETER(Reserved);\r
+\r
+       if (pathLength >= 14)\r
+       {\r
+               if ((lstrcmpi(&buf[pathLength-14], _T("\\ShellTest.exe"))) == 0)\r
+               {\r
+                       bInShellTest = TRUE;\r
+               }\r
+       }\r
+\r
+       if (!IsDebuggerPresent() && !bInShellTest)\r
+       {\r
+               TRACE(_T("In debug load preventer\n"));\r
+               return FALSE;\r
+       }\r
+#else\r
+       UNREFERENCED_PARAMETER(Reserved);\r
+#endif\r
+\r
+\r
+       switch(Reason)\r
+       {\r
+       case DLL_PROCESS_ATTACH:\r
+               hInst = hInstance;\r
+               break;\r
+\r
+               //case DLL_THREAD_ATTACH:\r
+               //  break;\r
+\r
+               //case DLL_THREAD_DETACH:\r
+               //  break;\r
+\r
+               //case DLL_PROCESS_DETACH:\r
+               //  break;\r
+       }\r
+\r
+       return TRUE;\r
+}\r
+\r
+\r
+STDAPI DllGetClassObject(REFCLSID rclsid, REFIID riid, LPVOID *ppv)\r
+{\r
+       TRACE(_T("DllGetClassObject() - Enter\n"));\r
+\r
+       LoadRealLibrary();\r
+       if (!pDllGetClassObject)\r
+       {\r
+               if (ppv)\r
+                       *ppv = NULL;\r
+               else\r
+                       ppv = NULL;\r
+\r
+               TRACE(_T("DllGetClassObject() - Bypass\n"));\r
+               return CLASS_E_CLASSNOTAVAILABLE;\r
+       }\r
+\r
+       TRACE(_T("DllGetClassObject() - Forward\n"));\r
+       return pDllGetClassObject(rclsid, riid, ppv);\r
+}\r
+\r
+STDAPI DllCanUnloadNow(void)\r
+{\r
+       HRESULT Result;\r
+\r
+       TRACE(_T("DllCanUnloadNow() - Enter\n"));\r
+\r
+       if (pDllCanUnloadNow)\r
+       {\r
+               TRACE(_T("DllCanUnloadNow() - Forward\n"));\r
+               Result = pDllCanUnloadNow();\r
+               if (Result != S_OK)\r
+                       return Result;\r
+       }\r
+\r
+       TRACE(_T("DllCanUnloadNow() - Unload\n"));\r
+       UnloadRealLibrary();\r
+       return S_OK;\r
+}\r
+\r
diff --git a/TortoiseShell/TortoiseStub.def b/TortoiseShell/TortoiseStub.def
new file mode 100644 (file)
index 0000000..167b35c
--- /dev/null
@@ -0,0 +1,6 @@
+LIBRARY TortoiseStub\r
+\r
+EXPORTS\r
+  DllGetClassObject PRIVATE\r
+  DllCanUnloadNow PRIVATE\r
+\r
diff --git a/TortoiseShell/TortoiseStub.rc b/TortoiseShell/TortoiseStub.rc
new file mode 100644 (file)
index 0000000..b5f6373
--- /dev/null
@@ -0,0 +1,47 @@
+#include <Windows.h>\r
+#ifdef _WIN32\r
+LANGUAGE LANG_NEUTRAL, SUBLANG_NEUTRAL\r
+#pragma code_page(1252)\r
+#endif //_WIN32\r
+\r
+/////////////////////////////////////////////////////////////////////////////\r
+//\r
+// Version\r
+//\r
+#include "..\version.h"\r
+VS_VERSION_INFO VERSIONINFO\r
+ FILEVERSION FILEVER\r
+ PRODUCTVERSION PRODUCTVER\r
+ FILEFLAGSMASK 0x3fL\r
+#ifdef _DEBUG\r
+ FILEFLAGS 0x1L\r
+#else\r
+ FILEFLAGS 0x0L\r
+#endif\r
+ FILEOS 0x4L\r
+ FILETYPE 0x1L\r
+ FILESUBTYPE 0x0L\r
+BEGIN\r
+    BLOCK "StringFileInfo"\r
+    BEGIN\r
+        BLOCK "040004e4"\r
+        BEGIN\r
+            VALUE "CompanyName", "http://tortoisesvn.net"\r
+            VALUE "FileDescription", "TortoiseSVN shell extension client"\r
+            VALUE "FileVersion", STRFILEVER\r
+            VALUE "InternalName", "TortoiseStub.dll"\r
+            VALUE "LegalCopyright", "Copyright (C) 2007"\r
+            VALUE "OriginalFilename", "TortoiseStub.dll"\r
+            VALUE "ProductName", "TortoiseSVN"\r
+            VALUE "ProductVersion", STRPRODUCTVER\r
+        END\r
+    END\r
+    BLOCK "VarFileInfo"\r
+    BEGIN\r
+        VALUE "Translation", 0x400, 1252\r
+    END\r
+END\r
+\r
+/////////////////////////////////////////////////////////////////////////////\r
+\r
+\r
diff --git a/TortoiseShell/TortoiseStub.vcproj b/TortoiseShell/TortoiseStub.vcproj
new file mode 100644 (file)
index 0000000..eb33c73
--- /dev/null
@@ -0,0 +1,489 @@
+<?xml version="1.0" encoding="Windows-1252"?>\r
+<VisualStudioProject\r
+       ProjectType="Visual C++"\r
+       Version="9.00"\r
+       Name="TortoiseStub"\r
+       ProjectGUID="{DB98402B-2CF6-4EC6-89F9-D19365EE8DE3}"\r
+       RootNamespace="TortoiseStub"\r
+       TargetFrameworkVersion="131072"\r
+       >\r
+       <Platforms>\r
+               <Platform\r
+                       Name="Win32"\r
+               />\r
+               <Platform\r
+                       Name="x64"\r
+               />\r
+       </Platforms>\r
+       <ToolFiles>\r
+       </ToolFiles>\r
+       <Configurations>\r
+               <Configuration\r
+                       Name="Debug|Win32"\r
+                       OutputDirectory="..\..\bin\Debug\bin"\r
+                       IntermediateDirectory="..\..\obj\TortoiseStub\Debug"\r
+                       ConfigurationType="2"\r
+                       UseOfMFC="0"\r
+                       ATLMinimizesCRunTimeLibraryUsage="false"\r
+                       CharacterSet="1"\r
+                       >\r
+                       <Tool\r
+                               Name="VCPreBuildEventTool"\r
+                       />\r
+                       <Tool\r
+                               Name="VCCustomBuildTool"\r
+                       />\r
+                       <Tool\r
+                               Name="VCXMLDataGeneratorTool"\r
+                       />\r
+                       <Tool\r
+                               Name="VCWebServiceProxyGeneratorTool"\r
+                       />\r
+                       <Tool\r
+                               Name="VCMIDLTool"\r
+                               PreprocessorDefinitions="_DEBUG"\r
+                               MkTypLibCompatible="true"\r
+                               SuppressStartupBanner="true"\r
+                               TargetEnvironment="1"\r
+                               TypeLibraryName=".\Debug/TortoiseStub.tlb"\r
+                               HeaderFileName=""\r
+                       />\r
+                       <Tool\r
+                               Name="VCCLCompilerTool"\r
+                               Optimization="0"\r
+                               AdditionalIncludeDirectories="../Utils"\r
+                               PreprocessorDefinitions="WIN32;DEBUG;_DEBUG;_WINDOWS;_USRDLL;_BIND_TO_CURRENT_CRT_VERSION;TORTOISESTUB_EXPORTS"\r
+                               MinimalRebuild="true"\r
+                               BasicRuntimeChecks="3"\r
+                               RuntimeLibrary="1"\r
+                               PrecompiledHeaderFile="$(IntDir)\$(TargetName).pch"\r
+                               AssemblerListingLocation="..\..\obj\TortoiseStub\Debug/"\r
+                               ObjectFile="..\..\obj\TortoiseStub\Debug/"\r
+                               ProgramDataBaseFileName="..\..\obj\TortoiseStub\Debug/"\r
+                               WarningLevel="4"\r
+                               SuppressStartupBanner="true"\r
+                               DebugInformationFormat="4"\r
+                       />\r
+                       <Tool\r
+                               Name="VCManagedResourceCompilerTool"\r
+                       />\r
+                       <Tool\r
+                               Name="VCResourceCompilerTool"\r
+                               PreprocessorDefinitions="_DEBUG"\r
+                               Culture="1033"\r
+                       />\r
+                       <Tool\r
+                               Name="VCPreLinkEventTool"\r
+                       />\r
+                       <Tool\r
+                               Name="VCLinkerTool"\r
+                               OutputFile="$(OutDir)/TortoiseStub.dll"\r
+                               LinkIncremental="2"\r
+                               SuppressStartupBanner="true"\r
+                               ModuleDefinitionFile=".\TortoiseStub.def"\r
+                               GenerateDebugInformation="true"\r
+                               ProgramDatabaseFile="$(OutDir)/TortoiseStub.pdb"\r
+                               RandomizedBaseAddress="1"\r
+                               DataExecutionPrevention="0"\r
+                               ImportLibrary="..\..\obj\TortoiseStub\Debug/TortoiseStub.lib"\r
+                               TargetMachine="1"\r
+                       />\r
+                       <Tool\r
+                               Name="VCALinkTool"\r
+                       />\r
+                       <Tool\r
+                               Name="VCManifestTool"\r
+                       />\r
+                       <Tool\r
+                               Name="VCXDCMakeTool"\r
+                       />\r
+                       <Tool\r
+                               Name="VCBscMakeTool"\r
+                               SuppressStartupBanner="true"\r
+                               OutputFile=".\Debug/TortoiseStub.bsc"\r
+                       />\r
+                       <Tool\r
+                               Name="VCFxCopTool"\r
+                       />\r
+                       <Tool\r
+                               Name="VCAppVerifierTool"\r
+                       />\r
+                       <Tool\r
+                               Name="VCPostBuildEventTool"\r
+                       />\r
+               </Configuration>\r
+               <Configuration\r
+                       Name="Debug|x64"\r
+                       OutputDirectory="..\..\bin\Debug64\bin"\r
+                       IntermediateDirectory="..\..\obj\TortoiseStub\Debug64"\r
+                       ConfigurationType="2"\r
+                       UseOfMFC="0"\r
+                       ATLMinimizesCRunTimeLibraryUsage="false"\r
+                       CharacterSet="1"\r
+                       >\r
+                       <Tool\r
+                               Name="VCPreBuildEventTool"\r
+                       />\r
+                       <Tool\r
+                               Name="VCCustomBuildTool"\r
+                       />\r
+                       <Tool\r
+                               Name="VCXMLDataGeneratorTool"\r
+                       />\r
+                       <Tool\r
+                               Name="VCWebServiceProxyGeneratorTool"\r
+                       />\r
+                       <Tool\r
+                               Name="VCMIDLTool"\r
+                               PreprocessorDefinitions="_DEBUG"\r
+                               MkTypLibCompatible="true"\r
+                               SuppressStartupBanner="true"\r
+                               TargetEnvironment="3"\r
+                               TypeLibraryName=".\Debug/TortoiseStub.tlb"\r
+                               HeaderFileName=""\r
+                       />\r
+                       <Tool\r
+                               Name="VCCLCompilerTool"\r
+                               Optimization="0"\r
+                               AdditionalIncludeDirectories="../Utils"\r
+                               PreprocessorDefinitions="WIN32;DEBUG;_DEBUG;_WINDOWS;_USRDLL;_BIND_TO_CURRENT_CRT_VERSION;TORTOISESTUB_EXPORTS"\r
+                               MinimalRebuild="true"\r
+                               BasicRuntimeChecks="3"\r
+                               RuntimeLibrary="1"\r
+                               PrecompiledHeaderFile="$(IntDir)\$(TargetName).pch"\r
+                               AssemblerListingLocation="..\..\obj\TortoiseStub\Debug64/"\r
+                               ObjectFile="..\..\obj\TortoiseStub\Debug64/"\r
+                               ProgramDataBaseFileName="..\..\obj\TortoiseStub\Debug64/"\r
+                               WarningLevel="4"\r
+                               SuppressStartupBanner="true"\r
+                               DebugInformationFormat="3"\r
+                       />\r
+                       <Tool\r
+                               Name="VCManagedResourceCompilerTool"\r
+                       />\r
+                       <Tool\r
+                               Name="VCResourceCompilerTool"\r
+                               PreprocessorDefinitions="_DEBUG"\r
+                               Culture="1033"\r
+                       />\r
+                       <Tool\r
+                               Name="VCPreLinkEventTool"\r
+                       />\r
+                       <Tool\r
+                               Name="VCLinkerTool"\r
+                               OutputFile="$(OutDir)/TortoiseStub.dll"\r
+                               LinkIncremental="2"\r
+                               SuppressStartupBanner="true"\r
+                               ModuleDefinitionFile=".\TortoiseStub.def"\r
+                               GenerateDebugInformation="true"\r
+                               ProgramDatabaseFile="$(OutDir)/TortoiseStub.pdb"\r
+                               RandomizedBaseAddress="1"\r
+                               DataExecutionPrevention="0"\r
+                               ImportLibrary="..\..\obj\TortoiseStub\Debug64/TortoiseStub.lib"\r
+                               TargetMachine="17"\r
+                       />\r
+                       <Tool\r
+                               Name="VCALinkTool"\r
+                       />\r
+                       <Tool\r
+                               Name="VCManifestTool"\r
+                       />\r
+                       <Tool\r
+                               Name="VCXDCMakeTool"\r
+                       />\r
+                       <Tool\r
+                               Name="VCBscMakeTool"\r
+                               SuppressStartupBanner="true"\r
+                               OutputFile=".\Debug/TortoiseStub.bsc"\r
+                       />\r
+                       <Tool\r
+                               Name="VCFxCopTool"\r
+                       />\r
+                       <Tool\r
+                               Name="VCAppVerifierTool"\r
+                       />\r
+                       <Tool\r
+                               Name="VCPostBuildEventTool"\r
+                       />\r
+               </Configuration>\r
+               <Configuration\r
+                       Name="Release|Win32"\r
+                       OutputDirectory="..\..\bin\Release\bin"\r
+                       IntermediateDirectory="..\..\obj\TortoiseStub\Release"\r
+                       ConfigurationType="2"\r
+                       UseOfMFC="0"\r
+                       ATLMinimizesCRunTimeLibraryUsage="false"\r
+                       CharacterSet="1"\r
+                       WholeProgramOptimization="1"\r
+                       >\r
+                       <Tool\r
+                               Name="VCPreBuildEventTool"\r
+                       />\r
+                       <Tool\r
+                               Name="VCCustomBuildTool"\r
+                       />\r
+                       <Tool\r
+                               Name="VCXMLDataGeneratorTool"\r
+                       />\r
+                       <Tool\r
+                               Name="VCWebServiceProxyGeneratorTool"\r
+                       />\r
+                       <Tool\r
+                               Name="VCMIDLTool"\r
+                               PreprocessorDefinitions="NDEBUG"\r
+                               MkTypLibCompatible="true"\r
+                               SuppressStartupBanner="true"\r
+                               TargetEnvironment="1"\r
+                               TypeLibraryName=".\Release/TortoiseStub.tlb"\r
+                               HeaderFileName=""\r
+                       />\r
+                       <Tool\r
+                               Name="VCCLCompilerTool"\r
+                               Optimization="3"\r
+                               InlineFunctionExpansion="0"\r
+                               FavorSizeOrSpeed="2"\r
+                               WholeProgramOptimization="true"\r
+                               AdditionalIncludeDirectories="../Utils"\r
+                               PreprocessorDefinitions="WIN32;NDEBUG;_WINDOWS;_USRDLL;_BIND_TO_CURRENT_CRT_VERSION;TORTOISESTUB_EXPORTS"\r
+                               StringPooling="true"\r
+                               ExceptionHandling="0"\r
+                               RuntimeLibrary="0"\r
+                               StructMemberAlignment="0"\r
+                               EnableFunctionLevelLinking="false"\r
+                               PrecompiledHeaderFile="$(IntDir)\$(TargetName).pch"\r
+                               AssemblerListingLocation="..\..\obj\TortoiseStub\Release/"\r
+                               ObjectFile="..\..\obj\TortoiseStub\Release/"\r
+                               ProgramDataBaseFileName="..\..\obj\TortoiseStub\Release/"\r
+                               WarningLevel="4"\r
+                               SuppressStartupBanner="true"\r
+                               CompileAs="1"\r
+                       />\r
+                       <Tool\r
+                               Name="VCManagedResourceCompilerTool"\r
+                       />\r
+                       <Tool\r
+                               Name="VCResourceCompilerTool"\r
+                               PreprocessorDefinitions="NDEBUG"\r
+                               Culture="1033"\r
+                       />\r
+                       <Tool\r
+                               Name="VCPreLinkEventTool"\r
+                       />\r
+                       <Tool\r
+                               Name="VCLinkerTool"\r
+                               OutputFile="$(OutDir)/TortoiseStub.dll"\r
+                               LinkIncremental="1"\r
+                               SuppressStartupBanner="true"\r
+                               ModuleDefinitionFile=".\TortoiseStub.def"\r
+                               ProgramDatabaseFile="$(OutDir)/TortoiseStub.pdb"\r
+                               SubSystem="2"\r
+                               EnableCOMDATFolding="2"\r
+                               OptimizeForWindows98="0"\r
+                               BaseAddress="0x5940000"\r
+                               RandomizedBaseAddress="1"\r
+                               DataExecutionPrevention="0"\r
+                               ImportLibrary="..\..\obj\TortoiseStub\Release/TortoiseStub.lib"\r
+                               TargetMachine="1"\r
+                       />\r
+                       <Tool\r
+                               Name="VCALinkTool"\r
+                       />\r
+                       <Tool\r
+                               Name="VCManifestTool"\r
+                       />\r
+                       <Tool\r
+                               Name="VCXDCMakeTool"\r
+                       />\r
+                       <Tool\r
+                               Name="VCBscMakeTool"\r
+                               SuppressStartupBanner="true"\r
+                               OutputFile=".\Release/TortoiseStub.bsc"\r
+                       />\r
+                       <Tool\r
+                               Name="VCFxCopTool"\r
+                       />\r
+                       <Tool\r
+                               Name="VCAppVerifierTool"\r
+                       />\r
+                       <Tool\r
+                               Name="VCPostBuildEventTool"\r
+                       />\r
+               </Configuration>\r
+               <Configuration\r
+                       Name="Release|x64"\r
+                       OutputDirectory="..\..\bin\Release64\bin"\r
+                       IntermediateDirectory="..\..\obj\TortoiseStub\Release64"\r
+                       ConfigurationType="2"\r
+                       UseOfMFC="0"\r
+                       ATLMinimizesCRunTimeLibraryUsage="false"\r
+                       CharacterSet="1"\r
+                       WholeProgramOptimization="1"\r
+                       >\r
+                       <Tool\r
+                               Name="VCPreBuildEventTool"\r
+                       />\r
+                       <Tool\r
+                               Name="VCCustomBuildTool"\r
+                       />\r
+                       <Tool\r
+                               Name="VCXMLDataGeneratorTool"\r
+                       />\r
+                       <Tool\r
+                               Name="VCWebServiceProxyGeneratorTool"\r
+                       />\r
+                       <Tool\r
+                               Name="VCMIDLTool"\r
+                               PreprocessorDefinitions="NDEBUG"\r
+                               MkTypLibCompatible="true"\r
+                               SuppressStartupBanner="true"\r
+                               TargetEnvironment="3"\r
+                               TypeLibraryName=".\Release/TortoiseStub.tlb"\r
+                               HeaderFileName=""\r
+                       />\r
+                       <Tool\r
+                               Name="VCCLCompilerTool"\r
+                               Optimization="3"\r
+                               InlineFunctionExpansion="0"\r
+                               FavorSizeOrSpeed="2"\r
+                               WholeProgramOptimization="true"\r
+                               AdditionalIncludeDirectories="../Utils"\r
+                               PreprocessorDefinitions="WIN32;NDEBUG;_WINDOWS;_USRDLL;_BIND_TO_CURRENT_CRT_VERSION;TORTOISESTUB_EXPORTS"\r
+                               StringPooling="true"\r
+                               ExceptionHandling="0"\r
+                               RuntimeLibrary="0"\r
+                               StructMemberAlignment="0"\r
+                               EnableFunctionLevelLinking="false"\r
+                               PrecompiledHeaderFile="$(IntDir)\$(TargetName).pch"\r
+                               AssemblerListingLocation="..\..\obj\TortoiseStub\Release64/"\r
+                               ObjectFile="..\..\obj\TortoiseStub\Release64/"\r
+                               ProgramDataBaseFileName="..\..\obj\TortoiseStub\Release64/"\r
+                               WarningLevel="4"\r
+                               SuppressStartupBanner="true"\r
+                               CompileAs="1"\r
+                       />\r
+                       <Tool\r
+                               Name="VCManagedResourceCompilerTool"\r
+                       />\r
+                       <Tool\r
+                               Name="VCResourceCompilerTool"\r
+                               PreprocessorDefinitions="NDEBUG"\r
+                               Culture="1033"\r
+                       />\r
+                       <Tool\r
+                               Name="VCPreLinkEventTool"\r
+                       />\r
+                       <Tool\r
+                               Name="VCLinkerTool"\r
+                               OutputFile="$(OutDir)/TortoiseStub.dll"\r
+                               LinkIncremental="1"\r
+                               SuppressStartupBanner="true"\r
+                               ModuleDefinitionFile=".\TortoiseStub.def"\r
+                               ProgramDatabaseFile="$(OutDir)/TortoiseStub.pdb"\r
+                               SubSystem="2"\r
+                               EnableCOMDATFolding="2"\r
+                               OptimizeForWindows98="1"\r
+                               BaseAddress="0x5940000"\r
+                               RandomizedBaseAddress="1"\r
+                               DataExecutionPrevention="0"\r
+                               ImportLibrary="..\..\obj\TortoiseStub\Release64/TortoiseStub.lib"\r
+                               TargetMachine="17"\r
+                       />\r
+                       <Tool\r
+                               Name="VCALinkTool"\r
+                       />\r
+                       <Tool\r
+                               Name="VCManifestTool"\r
+                       />\r
+                       <Tool\r
+                               Name="VCXDCMakeTool"\r
+                       />\r
+                       <Tool\r
+                               Name="VCBscMakeTool"\r
+                               SuppressStartupBanner="true"\r
+                               OutputFile=".\Release/TortoiseStub.bsc"\r
+                       />\r
+                       <Tool\r
+                               Name="VCFxCopTool"\r
+                       />\r
+                       <Tool\r
+                               Name="VCAppVerifierTool"\r
+                       />\r
+                       <Tool\r
+                               Name="VCPostBuildEventTool"\r
+                       />\r
+               </Configuration>\r
+       </Configurations>\r
+       <References>\r
+       </References>\r
+       <Files>\r
+               <Filter\r
+                       Name="Source Files"\r
+                       Filter="cpp;c;cxx;rc;def;r;odl;idl;hpj;bat"\r
+                       >\r
+                       <File\r
+                               RelativePath="..\Utils\Debug.c"\r
+                               >\r
+                       </File>\r
+                       <File\r
+                               RelativePath="TortoiseStub.c"\r
+                               >\r
+                               <FileConfiguration\r
+                                       Name="Debug|Win32"\r
+                                       >\r
+                                       <Tool\r
+                                               Name="VCCLCompilerTool"\r
+                                               PreprocessorDefinitions=""\r
+                                       />\r
+                               </FileConfiguration>\r
+                               <FileConfiguration\r
+                                       Name="Debug|x64"\r
+                                       >\r
+                                       <Tool\r
+                                               Name="VCCLCompilerTool"\r
+                                               PreprocessorDefinitions=""\r
+                                       />\r
+                               </FileConfiguration>\r
+                               <FileConfiguration\r
+                                       Name="Release|Win32"\r
+                                       >\r
+                                       <Tool\r
+                                               Name="VCCLCompilerTool"\r
+                                               PreprocessorDefinitions=""\r
+                                       />\r
+                               </FileConfiguration>\r
+                               <FileConfiguration\r
+                                       Name="Release|x64"\r
+                                       >\r
+                                       <Tool\r
+                                               Name="VCCLCompilerTool"\r
+                                               PreprocessorDefinitions=""\r
+                                       />\r
+                               </FileConfiguration>\r
+                       </File>\r
+                       <File\r
+                               RelativePath="TortoiseStub.def"\r
+                               >\r
+                       </File>\r
+               </Filter>\r
+               <Filter\r
+                       Name="Header Files"\r
+                       Filter="h;hpp;hxx;hm;inl"\r
+                       >\r
+                       <File\r
+                               RelativePath="..\Utils\Debug.h"\r
+                               >\r
+                       </File>\r
+               </Filter>\r
+               <Filter\r
+                       Name="Resource Files"\r
+                       Filter="ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe"\r
+                       >\r
+                       <File\r
+                               RelativePath=".\TortoiseStub.rc"\r
+                               >\r
+                       </File>\r
+               </Filter>\r
+       </Files>\r
+       <Globals>\r
+       </Globals>\r
+</VisualStudioProject>\r
diff --git a/TortoiseShell/deregister.registry b/TortoiseShell/deregister.registry
new file mode 100644 (file)
index 0000000..98e7d85
Binary files /dev/null and b/TortoiseShell/deregister.registry differ
diff --git a/TortoiseShell/register.registry b/TortoiseShell/register.registry
new file mode 100644 (file)
index 0000000..0c0344f
Binary files /dev/null and b/TortoiseShell/register.registry differ
diff --git a/TortoiseShell/registerrelease.registry b/TortoiseShell/registerrelease.registry
new file mode 100644 (file)
index 0000000..d7cf6e2
Binary files /dev/null and b/TortoiseShell/registerrelease.registry differ
diff --git a/TortoiseShell/resource.h b/TortoiseShell/resource.h
new file mode 100644 (file)
index 0000000..0283665
--- /dev/null
@@ -0,0 +1,231 @@
+//{{NO_DEPENDENCIES}}\r
+// Microsoft Visual C++ generated include file.\r
+// Used by resource.rc\r
+//\r
+#define IDD_PROPPAGE                    107\r
+#define IDI_APP                         108\r
+#define IDS_MENUCHECKOUT                120\r
+#define IDI_CHECKOUT                    121\r
+#define IDS_MENUUPDATE                  121\r
+#define IDS_MENUCOMMIT                  122\r
+#define IDI_UPDATE                      122\r
+#define IDS_MENUCREATEREPOS             123\r
+#define IDI_COMMIT                      123\r
+#define IDS_MENUADD                     124\r
+#define IDI_ADD                         124\r
+#define IDS_MENUREVERT                  125\r
+#define IDI_REVERT                      125\r
+#define IDS_MENUCLEANUP                 126\r
+#define IDI_CLEANUP                     126\r
+#define IDS_MENURESOLVE                 127\r
+#define IDI_RESOLVE                     127\r
+#define IDS_MENUSWITCH                  128\r
+#define IDI_SWITCH                      128\r
+#define IDS_MENUMERGE                   129\r
+#define IDI_MERGE                       129\r
+#define IDS_MENUBRANCH                  130\r
+#define IDI_IMPORT                      130\r
+#define IDS_MENUIMPORT                  131\r
+#define IDI_EXPORT                      131\r
+#define IDS_MENUEXPORT                  132\r
+#define IDI_COPY                        132\r
+#define IDS_MENUSETTINGS                133\r
+#define IDI_DELETE                      133\r
+#define IDS_MENUABOUT                   134\r
+#define IDI_RENAME                      134\r
+#define IDS_MENUSUBMENU                 135\r
+#define IDI_DIFF                        135\r
+#define IDS_MENUDESCCHECKOUT            136\r
+#define IDI_LOG                         136\r
+#define IDS_MENUDESCUPDATE              137\r
+#define IDI_ABOUT                       137\r
+#define IDS_MENUDESCCOMMIT              138\r
+#define IDI_SETTINGS                    138\r
+#define IDS_MENUDESCADD                 139\r
+#define IDI_CREATEREPOS                 139\r
+#define IDS_MENUDESCREVERT              140\r
+#define IDI_CONFLICT                    140\r
+#define IDS_MENUDESCCLEANUP             141\r
+#define IDI_RELOCATE                    141\r
+#define IDS_MENUDESCRESOLVE             142\r
+#define IDI_HELP                        142\r
+#define IDS_MENUDESCSWITCH              143\r
+#define IDI_SHOWCHANGED                 143\r
+#define IDS_MENUDESCIMPORT              144\r
+#define IDI_IGNORE                      144\r
+#define IDS_MENUDESCEXPORT              145\r
+#define IDS_MENUDESCABOUT               146\r
+#define IDS_MENUDESCCREATEREPOS         147\r
+#define IDS_MENUDESCCOPY                148\r
+#define IDS_MENUDESCMERGE               149\r
+#define IDS_MENUDESCSETTINGS            150\r
+#define IDS_MENUDESCDEFAULT             151\r
+#define IDS_STATUSNONE                  152\r
+#define IDS_STATUSUNVERSIONED           153\r
+#define IDS_STATUSNORMAL                154\r
+#define IDS_STATUSADDED                 155\r
+#define IDS_STATUSABSENT                156\r
+#define IDS_STATUSDELETED               157\r
+#define IDS_STATUSREPLACED              158\r
+#define IDS_STATUSMODIFIED              159\r
+#define IDS_STATUSMERGED                160\r
+#define IDS_STATUSCONFLICTED            161\r
+#define IDS_STATUSOBSTRUCTED            162\r
+#define IDS_PROPLOCKED                  163\r
+#define IDS_PROPPROPERTY                164\r
+#define IDS_PROPVALUE                   165\r
+#define IDS_MENURENAME                  166\r
+#define IDS_MENUDESCRENAME              167\r
+#define IDS_MENUREMOVE                  168\r
+#define IDS_MENUDESCREMOVE              169\r
+#define IDS_MENUUPDATEEXT               170\r
+#define IDS_MENUDESCUPDATEEXT           171\r
+#define IDS_COLTITLESTATUS              172\r
+#define IDS_COLDESCSTATUS               173\r
+#define IDS_COLTITLEREV                 174\r
+#define IDS_COLDESCREV                  175\r
+#define IDS_MENUDIFF                    176\r
+#define IDS_MENUDESCDIFF                177\r
+#define IDS_DROPCOPYADDMENU             178\r
+#define IDS_DROPMOVEMENU                179\r
+#define IDS_MENULOG                     180\r
+#define IDS_MENUDESCLOG                 181\r
+#define IDS_COLTITLEURL                 182\r
+#define IDS_COLDESCURL                  183\r
+#define IDS_COLTITLESHORTURL            184\r
+#define IDS_COLDESCSHORTURL             185\r
+#define IDS_MENUCONFLICT                186\r
+#define IDS_MENUDESCCONFLICT            187\r
+#define IDS_MENURELOCATE                188\r
+#define IDS_MENUDESCRELOCATE            189\r
+#define IDS_MENUHELP                    190\r
+#define IDS_MENUDESCHELP                191\r
+#define IDS_MENUSHOWCHANGED             192\r
+#define IDS_MENUDESCSHOWCHANGED         193\r
+#define IDS_MENUIGNORE                  194\r
+#define IDS_MENUDESCIGNORE              195\r
+#define IDS_STATUSINCOMPLETE            196\r
+#define IDS_STATUSIGNORED               197\r
+#define IDS_DROPCOPYMENU                198\r
+#define IDS_PROPWAITCANCEL              199\r
+#define IDS_SETPROPTITLE                200\r
+#define IDS_MENUREPOBROWSE              201\r
+#define IDS_MENUDESCREPOBROWSE          202\r
+#define IDS_MENUBLAME                   203\r
+#define IDS_STATUSEXTERNAL              204\r
+#define IDS_MENUDESCBLAME               205\r
+#define IDS_MENUCREATEPATCH             206\r
+#define IDS_MENUAPPLYPATCH              207\r
+#define IDS_MENUDESCCREATEPATCH         208\r
+#define IDS_MENUDESCAPPLYPATCH          209\r
+#define IDS_MENUMERGEALL                210\r
+#define IDS_MENUDESCMERGEALL            211\r
+#define IDS_MENUUNDOADD                 212\r
+#define IDS_MENUDESCUNDOADD             213\r
+#define IDS_MENUPREVDIFF                214\r
+#define IDS_MENUDESCPREVDIFF            215\r
+#define IDS_COLTITLEMIMETYPE            216\r
+#define IDS_COLDESCMIMETYPE             217\r
+#define IDS_DROPEXPORTMENU              218\r
+#define IDS_DROPEXPORTEXTENDEDMENU      219\r
+#define IDS_MENUIGNOREMULTIPLEMASK      220\r
+#define IDS_MENUCLIPPASTE               225\r
+#define IDS_MENUDESCCLIPPASTE           226\r
+#define IDS_ERR_PROPNOTONFILE           230\r
+#define IDS_MENUIGNOREMULTIPLE          231\r
+#define IDS_ERR_PROPNOMULTILINE         232\r
+#define IDS_MENUREVISIONGRAPH           233\r
+#define IDS_MENUDESCREVISIONGRAPH       234\r
+#define IDS_MENUUNIGNORE                237\r
+#define IDS_MENUDESCUNIGNORE            238\r
+#define IDS_MENU_LOCK                   240\r
+#define IDS_MENU_UNLOCK                 241\r
+#define IDS_MENUDESC_LOCK               242\r
+#define IDS_MENUDESC_UNLOCK             243\r
+#define IDS_MENU_UNLOCKFORCE            244\r
+#define IDS_MENUDESC_UNLOCKFORCE        245\r
+#define IDS_MENU_LOCKFORCE              246\r
+#define IDS_COLTITLEOWNER               247\r
+#define IDS_COLDESCOWNER                248\r
+#define IDS_DROPCOPYRENAMEMENU          250\r
+#define IDS_COLTITLEAUTHOR              251\r
+#define IDS_COLDESCAUTHOR               252\r
+#define IDS_FILEPROPONFOLDER            253\r
+#define IDS_PROPSNOTSAVED               254\r
+#define IDS_MENUADDASREPLACEMENT        255\r
+#define IDS_DROPMOVERENAMEMENU          256\r
+#define IDS_MENUPROPERTIES              257\r
+#define IDS_MENUDESCPROPERTIES          258\r
+#define IDS_COLTITLEEOLSTYLE            259\r
+#define IDS_COLDESCEOLSTYLE             260\r
+#define IDS_MENUURLDIFF                 261\r
+#define IDS_MENUDESCURLDIFF             262\r
+#define IDS_PROPBIN                     263\r
+#define IDS_MENUDELUNVERSIONED          268\r
+#define IDS_MENUDESCDELUNVERSIONED      269\r
+#define IDS_MENUREMOVEKEEP              271\r
+#define IDS_MENUDESCREMOVEKEEP          272\r
+#define IDS_YES                         273\r
+#define IDS_NO                          274\r
+#define IDS_SVN_DEPTH_INFINITE          300\r
+#define IDS_SVN_DEPTH_IMMEDIATE         301\r
+#define IDS_SVN_DEPTH_FILES             302\r
+#define IDS_SVN_DEPTH_EMPTY             303\r
+#define IDS_SVN_DEPTH_EXCLUDE           304\r
+#define IDS_SVN_DEPTH_UNKNOWN           305\r
+#define IDS_SVN_DEPTH_WORKING           306\r
+#define IDC_REVISION                    1001\r
+#define IDC_LOCKED                      1002\r
+#define IDC_REPOURL                     1003\r
+#define IDC_CREVISION                   1004\r
+#define IDC_CDATE                       1005\r
+#define IDC_AUTHOR                      1006\r
+#define IDC_TEXTSTATUS                  1007\r
+#define IDC_TEXTDATE                    1008\r
+#define IDC_PROPSTATUS                  1009\r
+#define IDC_PROPDATE                    1010\r
+#define IDC_PROPLIST                    1011\r
+#define IDC_SWITCHED                    1011\r
+#define IDC_ADDBUTTON                   1012\r
+#define IDC_COPIED                      1012\r
+#define IDC_REMOVEBUTTON                1013\r
+#define IDC_EDITNAME                    1014\r
+#define IDC_EDITVALUE                   1015\r
+#define IDC_SHOWLOG                     1016\r
+#define IDC_RECURSIVE                   1018\r
+#define IDS_SVN_USERCANCELLED           1181\r
+#define IDI_REPOBROWSE                  5145\r
+#define IDI_BLAME                       5146\r
+#define IDI_PATCH                       5147\r
+#define IDI_CREATEPATCH                 5150\r
+#define IDI_REVISIONGRAPH               5151\r
+#define IDI_LOCK                        5152\r
+#define IDI_UNLOCK                      5153\r
+#define IDI_MENUFILE                    5154\r
+#define IDI_MENUFOLDER                  5155\r
+#define IDI_MENULINK                    5156\r
+#define IDI_MENUMULTIPLE                5157\r
+#define IDI_PROPERTIES                  5158\r
+#define IDI_DELUNVERSIONED              5159\r
+#define IDI_APPSMALL                    5160\r
+#define IDI_CLIPPASTE                   5164\r
+#define IDC_LOCKOWNER                   11019\r
+#define IDC_LOCKDATE                    11020\r
+#define IDC_EDITPROPERTIES              11021\r
+#define IDC_REPOURLUNESCAPED            11022\r
+#define IDC_ESCAPEDURLLABEL             11023\r
+#define IDC_REPOUUID                    11024\r
+#define IDC_CHANGELIST                  11025\r
+#define IDC_DEPTHEDIT                   11026\r
+#define IDC_CHECKSUM                    11027\r
+\r
+// Next default values for new objects\r
+// \r
+#ifdef APSTUDIO_INVOKED\r
+#ifndef APSTUDIO_READONLY_SYMBOLS\r
+#define _APS_NEXT_RESOURCE_VALUE        5165\r
+#define _APS_NEXT_COMMAND_VALUE         40001\r
+#define _APS_NEXT_CONTROL_VALUE         11026\r
+#define _APS_NEXT_SYMED_VALUE           5101\r
+#endif\r
+#endif\r
diff --git a/TortoiseShell/resource.rc b/TortoiseShell/resource.rc
new file mode 100644 (file)
index 0000000..44592c4
--- /dev/null
@@ -0,0 +1,401 @@
+// Microsoft Visual C++ generated resource script.\r
+//\r
+#include "resource.h"\r
+\r
+#define APSTUDIO_READONLY_SYMBOLS\r
+/////////////////////////////////////////////////////////////////////////////\r
+//\r
+// Generated from the TEXTINCLUDE 2 resource.\r
+//\r
+#include "winres.h"\r
+\r
+/////////////////////////////////////////////////////////////////////////////\r
+#undef APSTUDIO_READONLY_SYMBOLS\r
+\r
+/////////////////////////////////////////////////////////////////////////////\r
+// Neutral resources\r
+\r
+#if !defined(AFX_RESOURCE_DLL) || defined(AFX_TARG_NEU)\r
+#ifdef _WIN32\r
+LANGUAGE LANG_NEUTRAL, SUBLANG_NEUTRAL\r
+#pragma code_page(1252)\r
+#endif //_WIN32\r
+\r
+/////////////////////////////////////////////////////////////////////////////\r
+//\r
+// Icon\r
+//\r
+\r
+// Icon with lowest ID value placed first to ensure application icon\r
+// remains consistent on all systems.\r
+IDI_APP                 ICON                    "..\\Resources\\Tortoise.ico"\r
+IDI_CHECKOUT            ICON                    "..\\Resources\\menucheckout.ico"\r
+IDI_UPDATE              ICON                    "..\\Resources\\menuupdate.ico"\r
+IDI_COMMIT              ICON                    "..\\Resources\\menucommit.ico"\r
+IDI_ADD                 ICON                    "..\\Resources\\menuadd.ico"\r
+IDI_REVERT              ICON                    "..\\Resources\\menurevert.ico"\r
+IDI_CLEANUP             ICON                    "..\\Resources\\menucleanup.ico"\r
+IDI_RESOLVE             ICON                    "..\\Resources\\menuresolve.ico"\r
+IDI_SWITCH              ICON                    "..\\Resources\\menuswitch.ico"\r
+IDI_MERGE               ICON                    "..\\Resources\\menumerge.ico"\r
+IDI_IMPORT              ICON                    "..\\Resources\\menuimport.ico"\r
+IDI_EXPORT              ICON                    "..\\Resources\\menuexport.ico"\r
+IDI_COPY                ICON                    "..\\Resources\\menucopy.ico"\r
+IDI_DELETE              ICON                    "..\\Resources\\menudelete.ico"\r
+IDI_RENAME              ICON                    "..\\Resources\\menurename.ico"\r
+IDI_DIFF                ICON                    "..\\Resources\\menucompare.ico"\r
+IDI_LOG                 ICON                    "..\\Resources\\menulog.ico"\r
+IDI_ABOUT               ICON                    "..\\Resources\\menuabout.ico"\r
+IDI_SETTINGS            ICON                    "..\\Resources\\menusettings.ico"\r
+IDI_CREATEREPOS         ICON                    "..\\Resources\\menucreaterepos.ico"\r
+IDI_CONFLICT            ICON                    "..\\Resources\\menuconflict.ico"\r
+IDI_RELOCATE            ICON                    "..\\Resources\\menurelocate.ico"\r
+IDI_HELP                ICON                    "..\\Resources\\menuhelp.ico"\r
+IDI_SHOWCHANGED         ICON                    "..\\Resources\\menushowchanged.ico"\r
+IDI_IGNORE              ICON                    "..\\Resources\\menuignore.ico"\r
+IDI_REPOBROWSE          ICON                    "..\\Resources\\menurepobrowse.ico"\r
+IDI_BLAME               ICON                    "..\\Resources\\menublame.ico"\r
+IDI_PATCH               ICON                    "..\\Resources\\menupatch.ico"\r
+IDI_CREATEPATCH         ICON                    "..\\Resources\\menudiff.ico"\r
+IDI_REVISIONGRAPH       ICON                    "..\\Resources\\menurevisiongraph.ico"\r
+IDI_LOCK                ICON                    "..\\Resources\\menulock.ico"\r
+IDI_UNLOCK              ICON                    "..\\Resources\\menuunlock.ico"\r
+IDI_MENUFILE            ICON                    "..\\Resources\\tsvnmenufile.ico"\r
+IDI_MENUFOLDER          ICON                    "..\\Resources\\tsvnmenufolder.ico"\r
+IDI_MENULINK            ICON                    "..\\Resources\\tsvnmenulink.ico"\r
+IDI_MENUMULTIPLE        ICON                    "..\\Resources\\tsvnmenumultiple.ico"\r
+IDI_PROPERTIES          ICON                    "..\\Resources\\menuproperties.ico"\r
+IDI_DELUNVERSIONED      ICON                    "..\\Resources\\menudelunversioned.ico"\r
+IDI_APPSMALL            ICON                    "..\\Resources\\TortoiseSmall.ico"\r
+IDI_CLIPPASTE           ICON                    "..\\Resources\\clippaste.ico"\r
+#endif    // Neutral resources\r
+/////////////////////////////////////////////////////////////////////////////\r
+\r
+\r
+/////////////////////////////////////////////////////////////////////////////\r
+// English (U.S.) resources\r
+\r
+#if !defined(AFX_RESOURCE_DLL) || defined(AFX_TARG_ENU)\r
+#ifdef _WIN32\r
+LANGUAGE LANG_ENGLISH, SUBLANG_ENGLISH_US\r
+#pragma code_page(1252)\r
+#endif //_WIN32\r
+\r
+/////////////////////////////////////////////////////////////////////////////\r
+//\r
+// Dialog\r
+//\r
+\r
+IDD_PROPPAGE DIALOGEX 0, 0, 247, 277\r
+STYLE DS_SETFONT | DS_3DLOOK | DS_FIXEDSYS | WS_CHILD | WS_VISIBLE | WS_CAPTION\r
+CAPTION "Property Page"\r
+FONT 8, "MS Shell Dlg", 0, 0, 0x1\r
+BEGIN\r
+    LTEXT           "URL:",IDC_STATIC,4,5,26,8\r
+    EDITTEXT        IDC_REPOURL,30,5,213,12,ES_AUTOHSCROLL | ES_READONLY | NOT WS_BORDER,WS_EX_TRANSPARENT\r
+    LTEXT           "URL:",IDC_ESCAPEDURLLABEL,4,17,26,8\r
+    EDITTEXT        IDC_REPOURLUNESCAPED,29,17,214,14,ES_AUTOHSCROLL | ES_READONLY | NOT WS_BORDER\r
+    LTEXT           "Revision / Author:",IDC_STATIC,4,31,76,8\r
+    EDITTEXT        IDC_REVISION,80,31,40,12,ES_AUTOHSCROLL | ES_READONLY | NOT WS_BORDER,WS_EX_TRANSPARENT\r
+    EDITTEXT        IDC_AUTHOR,120,31,94,12,ES_AUTOHSCROLL | ES_READONLY | NOT WS_BORDER,WS_EX_TRANSPARENT\r
+    LTEXT           "Last commit revision:",IDC_STATIC,4,43,76,8\r
+    EDITTEXT        IDC_CREVISION,80,43,40,12,ES_AUTOHSCROLL | ES_READONLY | NOT WS_BORDER,WS_EX_TRANSPARENT\r
+    EDITTEXT        IDC_CDATE,120,43,123,12,ES_AUTOHSCROLL | ES_READONLY | NOT WS_BORDER,WS_EX_TRANSPARENT\r
+    LTEXT           "Text Status:",IDC_STATIC,4,55,76,8\r
+    EDITTEXT        IDC_TEXTSTATUS,80,55,40,12,ES_AUTOHSCROLL | ES_READONLY | NOT WS_BORDER,WS_EX_TRANSPARENT\r
+    EDITTEXT        IDC_TEXTDATE,120,55,123,12,ES_AUTOHSCROLL | ES_READONLY | NOT WS_BORDER,WS_EX_TRANSPARENT\r
+    LTEXT           "Property Status:",IDC_STATIC,4,67,76,8\r
+    EDITTEXT        IDC_PROPSTATUS,80,67,40,12,ES_AUTOHSCROLL | ES_READONLY | NOT WS_BORDER,WS_EX_TRANSPARENT\r
+    EDITTEXT        IDC_PROPDATE,120,67,123,12,ES_AUTOHSCROLL | ES_READONLY | NOT WS_BORDER,WS_EX_TRANSPARENT\r
+    LTEXT           "Lock owner:",IDC_STATIC,4,79,76,8\r
+    EDITTEXT        IDC_LOCKOWNER,80,79,163,12,ES_AUTOHSCROLL | ES_READONLY | NOT WS_BORDER\r
+    LTEXT           "Lock creation date:",IDC_STATIC,4,91,76,8\r
+    EDITTEXT        IDC_LOCKDATE,80,90,163,12,ES_AUTOHSCROLL | ES_READONLY | NOT WS_BORDER\r
+    LTEXT           "Repository UUID:",IDC_STATIC,4,103,76,8\r
+    EDITTEXT        IDC_REPOUUID,80,102,163,12,ES_AUTOHSCROLL | ES_READONLY | NOT WS_BORDER\r
+    LTEXT           "Changelist:",IDC_STATIC,4,115,76,8\r
+    EDITTEXT        IDC_CHANGELIST,80,114,163,12,ES_AUTOHSCROLL | ES_READONLY | NOT WS_BORDER\r
+    LTEXT           "Depth:",IDC_STATIC,4,127,76,8\r
+    EDITTEXT        IDC_DEPTHEDIT,80,126,163,12,ES_AUTOHSCROLL | ES_READONLY | NOT WS_BORDER\r
+    LTEXT           "Checksum:",IDC_STATIC,4,139,76,8\r
+    EDITTEXT        IDC_CHECKSUM,80,138,163,12,ES_AUTOHSCROLL | ES_READONLY | NOT WS_BORDER\r
+    LTEXT           "locked:",IDC_STATIC,4,151,76,8\r
+    LTEXT           "yes",IDC_LOCKED,80,150,163,8\r
+    LTEXT           "switched:",IDC_STATIC,4,163,76,8\r
+    LTEXT           "yes",IDC_SWITCHED,80,162,163,8\r
+    LTEXT           "copied:",IDC_STATIC,4,175,76,8\r
+    LTEXT           "yes",IDC_COPIED,80,174,163,8\r
+    PUSHBUTTON      "&Properties...",IDC_EDITPROPERTIES,4,191,107,14\r
+    PUSHBUTTON      "Show &log",IDC_SHOWLOG,120,191,123,14\r
+END\r
+\r
+\r
+#ifdef APSTUDIO_INVOKED\r
+/////////////////////////////////////////////////////////////////////////////\r
+//\r
+// TEXTINCLUDE\r
+//\r
+\r
+1 TEXTINCLUDE \r
+BEGIN\r
+    "resource.h\0"\r
+END\r
+\r
+2 TEXTINCLUDE \r
+BEGIN\r
+    "#include ""winres.h""\r\n"\r
+    "\0"\r
+END\r
+\r
+3 TEXTINCLUDE \r
+BEGIN\r
+    "LANGUAGE 9, 1\r\n"\r
+    "#pragma code_page(1252)\r\n"\r
+    "#include ""resource.rc2""  // non-Microsoft Visual C++ edited resources\r\n"\r
+    "\0"\r
+END\r
+\r
+#endif    // APSTUDIO_INVOKED\r
+\r
+\r
+/////////////////////////////////////////////////////////////////////////////\r
+//\r
+// DESIGNINFO\r
+//\r
+\r
+#ifdef APSTUDIO_INVOKED\r
+GUIDELINES DESIGNINFO \r
+BEGIN\r
+    IDD_PROPPAGE, DIALOG\r
+    BEGIN\r
+        VERTGUIDE, 4\r
+        VERTGUIDE, 30\r
+        VERTGUIDE, 80\r
+        VERTGUIDE, 120\r
+        VERTGUIDE, 243\r
+    END\r
+END\r
+#endif    // APSTUDIO_INVOKED\r
+\r
+\r
+/////////////////////////////////////////////////////////////////////////////\r
+//\r
+// String Table\r
+//\r
+\r
+STRINGTABLE \r
+BEGIN\r
+    IDS_MENUCHECKOUT        "Chec&kout..."\r
+    IDS_MENUUPDATE          "&Update"\r
+    IDS_MENUCOMMIT          "&Commit..."\r
+    IDS_MENUCREATEREPOS     "Create repositor&y here"\r
+    IDS_MENUADD             "&Add..."\r
+    IDS_MENUREVERT          "Re&vert..."\r
+    IDS_MENUCLEANUP         "&Clean up"\r
+    IDS_MENURESOLVE         "Res&olved..."\r
+END\r
+\r
+STRINGTABLE \r
+BEGIN\r
+    IDS_MENUSWITCH          "S&witch..."\r
+    IDS_MENUMERGE           "&Merge..."\r
+    IDS_MENUBRANCH          "Branch/&tag..."\r
+    IDS_MENUIMPORT          "&Import..."\r
+    IDS_MENUEXPORT          "E&xport..."\r
+    IDS_MENUSETTINGS        "&Settings"\r
+    IDS_MENUABOUT           "A&bout"\r
+    IDS_MENUSUBMENU         "&TortoiseSVN"\r
+    IDS_MENUDESCCHECKOUT    "Check out a working copy from a repository"\r
+    IDS_MENUDESCUPDATE      "Updates the working copy to the current revision"\r
+    IDS_MENUDESCCOMMIT      "Commits your changes to the repository"\r
+    IDS_MENUDESCADD         "Adds file(s) to Subversion control"\r
+    IDS_MENUDESCREVERT      "Reverts all changes you made since the last update"\r
+    IDS_MENUDESCCLEANUP     "Cleanup interrupted operations, locked files, ..."\r
+    IDS_MENUDESCRESOLVE     "Resolves conflicted files"\r
+    IDS_MENUDESCSWITCH      "Switch working copy to another branch / tag"\r
+END\r
+\r
+STRINGTABLE \r
+BEGIN\r
+    IDS_MENUDESCIMPORT      "Imports the directory to a repository"\r
+    IDS_MENUDESCEXPORT      "Exports a repository to a clean working copy without the svn administrative folders"\r
+    IDS_MENUDESCABOUT       "Shows information about TortoiseSVN"\r
+    IDS_MENUDESCCREATEREPOS "Creates a repository database at the current location"\r
+    IDS_MENUDESCCOPY        "Creates a 'cheap' copy inside the repository used for branches or tagging"\r
+    IDS_MENUDESCMERGE       "Merges a branch into the main trunk"\r
+    IDS_MENUDESCSETTINGS    "Tweak TortoiseSVN"\r
+    IDS_MENUDESCDEFAULT     "no description for this command is available"\r
+    IDS_STATUSNONE          " "\r
+    IDS_STATUSUNVERSIONED   "non-versioned"\r
+    IDS_STATUSNORMAL        "normal"\r
+    IDS_STATUSADDED         "added"\r
+    IDS_STATUSABSENT        "missing"\r
+    IDS_STATUSDELETED       "deleted"\r
+    IDS_STATUSREPLACED      "replaced"\r
+    IDS_STATUSMODIFIED      "modified"\r
+END\r
+\r
+STRINGTABLE \r
+BEGIN\r
+    IDS_STATUSMERGED        "merged"\r
+    IDS_STATUSCONFLICTED    "conflicted"\r
+    IDS_STATUSOBSTRUCTED    "obstructed"\r
+    IDS_PROPLOCKED          "locked"\r
+    IDS_PROPPROPERTY        "Property"\r
+    IDS_PROPVALUE           "Value"\r
+    IDS_MENURENAME          "Re&name..."\r
+    IDS_MENUDESCRENAME      "Renames files / folders inside version control"\r
+    IDS_MENUREMOVE          "&Delete"\r
+    IDS_MENUDESCREMOVE      "Deletes files / folders from version control"\r
+    IDS_MENUUPDATEEXT       "&Update to revision..."\r
+    IDS_MENUDESCUPDATEEXT   "Updates the working copy to a specific revision"\r
+    IDS_COLTITLESTATUS      "SVN Status"\r
+    IDS_COLDESCSTATUS       "Status of item in SVN"\r
+    IDS_COLTITLEREV         "SVN Revision"\r
+    IDS_COLDESCREV          "Last saved revision of item"\r
+END\r
+\r
+STRINGTABLE \r
+BEGIN\r
+    IDS_MENUSHOWCHANGED     "Check for modi&fications"\r
+    IDS_MENUDESCSHOWCHANGED "Shows all files which were changed since the last update, locally and in the repository"\r
+    IDS_MENUIGNORE          "Add to &ignore list"\r
+    IDS_MENUDESCIGNORE      "Adds the selected file(s) or the filemask to the 'ignore' list"\r
+    IDS_STATUSINCOMPLETE    "incomplete"\r
+    IDS_STATUSIGNORED       "ignored"\r
+    IDS_DROPCOPYMENU        "SVN Copy versioned item(s) here"\r
+    IDS_PROPWAITCANCEL      "Please wait while cancelling..."\r
+    IDS_SETPROPTITLE        "Setting properties..."\r
+    IDS_MENUREPOBROWSE      "&Repo-browser"\r
+    IDS_MENUDESCREPOBROWSE  "Opens the repository browser to tweak the repository online"\r
+    IDS_MENUBLAME           "&Blame..."\r
+    IDS_STATUSEXTERNAL      "external"\r
+    IDS_MENUDESCBLAME       "Blames each line of a file on an author"\r
+    IDS_MENUCREATEPATCH     "Create &patch..."\r
+    IDS_MENUAPPLYPATCH      "Apply &patch..."\r
+END\r
+\r
+STRINGTABLE \r
+BEGIN\r
+    IDS_MENUDIFF            "&Diff"\r
+    IDS_MENUDESCDIFF        "Compares the file with the last committed revision to show you the changes you made"\r
+    IDS_DROPCOPYADDMENU     "SVN Copy and add files to this WC"\r
+    IDS_DROPMOVEMENU        "SVN Move versioned item(s) here"\r
+    IDS_MENULOG             "Show &log"\r
+    IDS_MENUDESCLOG         "Shows the log for the selected file / folder"\r
+    IDS_COLTITLEURL         "SVN URL"\r
+    IDS_COLDESCURL          "URL of Subversion items"\r
+    IDS_COLTITLESHORTURL    "SVN short URL"\r
+    IDS_COLDESCSHORTURL     "Short URL of Subversion items"\r
+    IDS_MENUCONFLICT        "&Edit conflicts"\r
+    IDS_MENUDESCCONFLICT    "Launches the external diff / merge program to solve the conflicts"\r
+    IDS_MENURELOCATE        "Relo&cate..."\r
+    IDS_MENUDESCRELOCATE    "Use this if the URL of the repository has changed"\r
+    IDS_MENUHELP            "&Help"\r
+    IDS_MENUDESCHELP        "Read the 'Daily Use Guide' before you are stuck..."\r
+END\r
+\r
+STRINGTABLE \r
+BEGIN\r
+    IDS_MENUDESCCREATEPATCH "Creates a unified diff file with all changes you made"\r
+    IDS_MENUDESCAPPLYPATCH  "Applies a unified diff file to the working copy"\r
+    IDS_MENUMERGEALL        "Merge reintegrate..."\r
+    IDS_MENUDESCMERGEALL    "Merges all missing revisions back into the working copy using merge-tracking information"\r
+    IDS_MENUUNDOADD         "Undo Add.."\r
+    IDS_MENUDESCUNDOADD     "Reverts an addition to version control"\r
+    IDS_MENUPREVDIFF        "&Diff with previous version"\r
+    IDS_MENUDESCPREVDIFF    "Diffs the working copy file with the one before the last commit."\r
+    IDS_COLTITLEMIMETYPE    "SVN mime-type"\r
+    IDS_COLDESCMIMETYPE     "Shows the mime type of the versioned file"\r
+    IDS_DROPEXPORTMENU      "SVN Export versioned items here"\r
+    IDS_DROPEXPORTEXTENDEDMENU "SVN Export all items here"\r
+    IDS_MENUIGNOREMULTIPLEMASK "Ignore items by &extension"\r
+END\r
+\r
+STRINGTABLE \r
+BEGIN\r
+    IDS_MENUCLIPPASTE       "&Paste"\r
+    IDS_MENUDESCCLIPPASTE   "Pastes the svn path from the clipboard, resulting in a move (cut) or copy operation"\r
+    IDS_ERR_PROPNOTONFILE   "This property is only allowed on folders, not files."\r
+    IDS_MENUIGNOREMULTIPLE  "&Ignore %d items by name"\r
+    IDS_ERR_PROPNOMULTILINE "This property must not have multiple lines. Only one line is allowed."\r
+    IDS_MENUREVISIONGRAPH   "Revision &graph"\r
+    IDS_MENUDESCREVISIONGRAPH \r
+                            "Shows a graphical representation of copies/tags/branches"\r
+    IDS_MENUUNIGNORE        "Remove from &ignore list"\r
+    IDS_MENUDESCUNIGNORE    "Removes the file or filemask from the list of ignored items"\r
+END\r
+\r
+STRINGTABLE \r
+BEGIN\r
+    IDS_DROPMOVERENAMEMENU  "SVN Move and rename versioned item here"\r
+    IDS_MENUPROPERTIES      "Properties"\r
+    IDS_MENUDESCPROPERTIES  "Manage Subversion properties"\r
+    IDS_COLTITLEEOLSTYLE    "SVN eol-style"\r
+    IDS_COLDESCEOLSTYLE     "Shows the eol-style property value"\r
+    IDS_MENUURLDIFF         "&Diff with URL"\r
+    IDS_MENUDESCURLDIFF     "Compares the selected file with a file in the repository"\r
+    IDS_PROPBIN             "(binary value)"\r
+    IDS_MENUDELUNVERSIONED  "Delete unversioned items..."\r
+    IDS_MENUDESCDELUNVERSIONED "Removes all unversioned and ignored items"\r
+    IDS_MENUREMOVEKEEP      "&Delete (keep local)"\r
+END\r
+\r
+STRINGTABLE \r
+BEGIN\r
+    IDS_MENU_LOCK           "Get loc&k..."\r
+    IDS_MENU_UNLOCK         "Release loc&k"\r
+    IDS_MENUDESC_LOCK       "Locks a file for other users and makes it editable by you."\r
+    IDS_MENUDESC_UNLOCK     "Releases locks on files so other users can edit them again."\r
+    IDS_MENU_UNLOCKFORCE    "Break loc&k"\r
+    IDS_MENUDESC_UNLOCKFORCE \r
+                            "Releases locks even if you're not the owner of the locks (breaks them)."\r
+    IDS_MENU_LOCKFORCE      "Steal loc&k"\r
+    IDS_COLTITLEOWNER       "SVN Local lock owner"\r
+    IDS_COLDESCOWNER        "The user who owns the lock of the file"\r
+    IDS_DROPCOPYRENAMEMENU  "SVN Copy and rename versioned item here"\r
+    IDS_COLTITLEAUTHOR      "SVN Author"\r
+    IDS_COLDESCAUTHOR       "The user who did the last commit"\r
+    IDS_FILEPROPONFOLDER    "You can't set this property on folders, only on files!\nIf you want to set it on all files within that folder,\nyou must activate the 'recursive' checkbox."\r
+    IDS_PROPSNOTSAVED       "You have modified properties without saving them first.\nDo you want to save them now?"\r
+    IDS_MENUADDASREPLACEMENT "Add (as replacement)..."\r
+END\r
+\r
+STRINGTABLE \r
+BEGIN\r
+    IDS_MENUDESCREMOVEKEEP  "Deletes files / folders from version control but keeps the file"\r
+    IDS_YES                 "yes"\r
+    IDS_NO                  "no"\r
+END\r
+\r
+STRINGTABLE \r
+BEGIN\r
+    IDS_SVN_DEPTH_INFINITE  "Fully recursive"\r
+    IDS_SVN_DEPTH_IMMEDIATE "Immediate children, including folders"\r
+    IDS_SVN_DEPTH_FILES     "Only file children"\r
+    IDS_SVN_DEPTH_EMPTY     "Only this item"\r
+END\r
+\r
+STRINGTABLE \r
+BEGIN\r
+    IDS_SVN_DEPTH_UNKNOWN   "Unknown depth"\r
+    IDS_SVN_DEPTH_WORKING   "Working copy"\r
+END\r
+\r
+#endif    // English (U.S.) resources\r
+/////////////////////////////////////////////////////////////////////////////\r
+\r
+\r
+\r
+#ifndef APSTUDIO_INVOKED\r
+/////////////////////////////////////////////////////////////////////////////\r
+//\r
+// Generated from the TEXTINCLUDE 3 resource.\r
+//\r
+LANGUAGE 9, 1\r
+#pragma code_page(1252)\r
+#include "resource.rc2"  // non-Microsoft Visual C++ edited resources\r
+\r
+/////////////////////////////////////////////////////////////////////////////\r
+#endif    // not APSTUDIO_INVOKED\r
+\r
diff --git a/TortoiseShell/resource.rc2 b/TortoiseShell/resource.rc2
new file mode 100644 (file)
index 0000000..efa683a
--- /dev/null
@@ -0,0 +1,9 @@
+/////////////////////////////////////////////////////////////////////////////\r
+//\r
+// RT_MANIFEST\r
+//\r
+#ifdef TSVNSHELL\r
+\r
+#include "..\\Resources\\TortoiseShell.rc2"  // non-Microsoft Visual C++ edited resources\r
+\r
+#endif\r
diff --git a/TortoiseShell/stdafx.cpp b/TortoiseShell/stdafx.cpp
new file mode 100644 (file)
index 0000000..e0cacce
--- /dev/null
@@ -0,0 +1,7 @@
+// stdafx.cpp : source file that includes just the standard includes\r
+// TortoiseProc.pch will be the pre-compiled header\r
+// stdafx.obj will contain the pre-compiled type information\r
+\r
+#include "stdafx.h"\r
+\r
+\r
diff --git a/TortoiseShell/stdafx.h b/TortoiseShell/stdafx.h
new file mode 100644 (file)
index 0000000..ef4f35e
--- /dev/null
@@ -0,0 +1,62 @@
+// stdafx.h : include file for standard system include files,\r
+// or project specific include files that are used frequently,\r
+// but are changed infrequently\r
+\r
+#pragma once\r
+// Modify the following defines if you have to target a platform prior to the ones specified below.\r
+// Refer to MSDN for the latest info on corresponding values for different platforms.\r
+#ifndef WINVER                         // Allow use of features specific to Windows 95 and Windows NT 4 or later.\r
+#      define WINVER 0x0501            // Change this to the appropriate value to target Windows 98 and Windows 2000 or later.\r
+#endif\r
+\r
+#ifndef _WIN32_WINNT           // Allow use of features specific to Windows NT 4 or later.\r
+#      define _WIN32_WINNT 0x0501              // Change this to the appropriate value to target Windows 98 and Windows 2000 or later.\r
+#endif                                         \r
+\r
+#ifndef _WIN32_WINDOWS         // Allow use of features specific to Windows 98 or later.\r
+#      define _WIN32_WINDOWS 0x0501 // Change this to the appropriate value to target Windows Me or later.\r
+#endif\r
+\r
+#ifndef _WIN32_IE                      // Allow use of features specific to IE 4.0 or later.\r
+#      define _WIN32_IE 0x0500 // Change this to the appropriate value to target IE 5.0 or later.\r
+#endif\r
+\r
+#define ISOLATION_AWARE_ENABLED 1\r
+\r
+#include <WinSock2.h>\r
+#include <Ws2tcpip.h>\r
+#include <Wspiapi.h>\r
+#include <windows.h>\r
+\r
+#include <commctrl.h>\r
+#include <Shlobj.h>\r
+#include <Shlwapi.h>\r
+#include <tchar.h>\r
+#include <wininet.h>\r
+#include <Aclapi.h>\r
+\r
+#include <atlbase.h>\r
+#include <atlexcept.h>\r
+#include <atlstr.h>\r
+\r
+#pragma warning(push)\r
+#pragma warning(disable: 4702) // Unreachable code warnings in xtree\r
+#include <string>\r
+#include <set>\r
+#include <map>\r
+#include <vector> \r
+#include <algorithm> \r
+#pragma warning(pop)\r
+\r
+#pragma warning(push)\r
+#include "apr_general.h"\r
+#include "svn_pools.h"\r
+#include "svn_client.h"\r
+#include "svn_path.h"\r
+#include "svn_wc.h"\r
+#include "svn_utf.h"\r
+#include "svn_config.h"\r
+#include "svn_subst.h"\r
+#pragma warning(pop)\r
+\r
+#define CSTRING_AVAILABLE\r