--- /dev/null
+// 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
--- /dev/null
+// 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
--- /dev/null
+/**\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
--- /dev/null
+// 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
--- /dev/null
+// 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
--- /dev/null
+// 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
--- /dev/null
+// 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
--- /dev/null
+// 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
--- /dev/null
+// 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
--- /dev/null
+// 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
--- /dev/null
+// 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
--- /dev/null
+// 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
--- /dev/null
+// 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
--- /dev/null
+// 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
--- /dev/null
+// 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
--- /dev/null
+// 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
--- /dev/null
+// 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
--- /dev/null
+// 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
--- /dev/null
+;shellext.def : Declares the module parameters for the DLL.\r
+\r
+LIBRARY TORTOISESVN\r
+\r
+EXPORTS\r
+ DllCanUnloadNow private\r
+ DllGetClassObject private\r
--- /dev/null
+// 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
--- /dev/null
+// 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
--- /dev/null
+// 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
--- /dev/null
+// 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
--- /dev/null
+<?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=""../../ext/apr-util/include";"../../ext/apr-util/xml/expat/lib";../../ext/Subversion/subversion/include;../../ext/apr/include;../Utils;..\TortoiseShell;..\SVN;"..\..\ext\libintl\libintl3-win32\inc";..\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=""../../ext/apr-util/include";"../../ext/apr-util/xml/expat/lib";../../ext/Subversion/subversion/include;../../ext/apr/include;..\TortoiseShell;..\Utils;..\svn;"..\..\ext\libintl\libintl3-win32\inc";..\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=""../../ext/apr-util/include";"../../ext/apr-util/xml/expat/lib";../../ext/Subversion/subversion/include;../../ext/apr/include;../Utils;..\TortoiseShell;..\SVN;"..\..\ext\libintl\libintl3-x64\inc";..\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=""../../ext/apr-util/include";"../../ext/apr-util/xml/expat/lib";../../ext/Subversion/subversion/include;../../ext/apr/include;..\TortoiseShell;..\Utils;..\svn;"..\..\ext\libintl\libintl3-x64\inc";..\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
--- /dev/null
+// 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
--- /dev/null
+LIBRARY TortoiseStub\r
+\r
+EXPORTS\r
+ DllGetClassObject PRIVATE\r
+ DllCanUnloadNow PRIVATE\r
+\r
--- /dev/null
+#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
--- /dev/null
+<?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
--- /dev/null
+//{{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
--- /dev/null
+// 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
--- /dev/null
+/////////////////////////////////////////////////////////////////////////////\r
+//\r
+// RT_MANIFEST\r
+//\r
+#ifdef TSVNSHELL\r
+\r
+#include "..\\Resources\\TortoiseShell.rc2" // non-Microsoft Visual C++ edited resources\r
+\r
+#endif\r
--- /dev/null
+// 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
--- /dev/null
+// 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