Changeset c3caaf07dbcc…
Parent 98b4ee7b4057…
by
Changes to 22 files · Browse files at c3caaf07dbcc Showing diff from parent 98b4ee7b4057 Diff from another changeset...
|
|
@@ -0,0 +1,334 @@ + #include "stdafx.h"
+#include "ShellExt.h"
+#include "TortoiseUtils.h"
+
+#define CALL_MEMBER_FN(object,ptrToMember) ((object).*(ptrToMember))
+typedef STDMETHODIMP (CShellExt::*MenuAction)
+ (HWND hParent, LPCSTR pszWorkingDir, LPCSTR pszCmd, LPCSTR pszParam,
+ int iShowCmd);
+
+typedef struct {
+ std::string name;
+ std::string menuText;
+ std::string helpText;
+ std::string iconName;
+ MenuAction action;
+ int idCmd;
+ ULONG flags;
+} MenuDescription;
+
+typedef std::map<std::string, MenuDescription> MenuDescriptionMap;
+typedef std::map<int, MenuDescription> MenuIdCmdMap;
+
+
+MenuDescription menuDescList[] = {
+ {"commit", "HG Commit...", "Commit changes in repository",
+ "menucommit.ico", &CShellExt::CM_Commit, 0, 0},
+ {"status", "View File Status", "Repository status & changes",
+ "menushowchanged.ico", &CShellExt::CM_Status, 0, 0},
+ {"log", "View Changelog", "View change history in repository",
+ "menulog.ico", &CShellExt::CM_Log, 0, 0},
+ {"synch", "Synchronize", "Synchronize with remote repository",
+ "menusynch.ico", &CShellExt::CM_Synch, 0, 0},
+ {"serve", "Web Server", "Start web server for this repository",
+ "proxy.ico", &CShellExt::CM_Serve, 0, 0},
+ {"update", "Update To Revision", "Update working directory",
+ "menucheckout.ico", &CShellExt::CM_Update, 0, 0},
+ {"recover", "Recovery...", "General repair and recovery of repositor",
+ "general.ico", &CShellExt::CM_Recover, 0, 0},
+ {"userconf", "Global Settings", "Configure user wide settings",
+ "settings_user.ico", &CShellExt::CM_Userconf, 0, 0},
+ {"repoconf", "Repository Settings", "Configure settings local to this repository",
+ "settings_repo.ico", &CShellExt::CM_Repoconf, 0, 0},
+ {"about", "About...", "Show About Dialog",
+ "menuabout.ico", &CShellExt::CM_About, 0, 0},
+
+ // template
+ {"", "", "",
+ ".ico", NULL, 0, 0},
+};
+
+MenuDescriptionMap MenuDescMap;
+MenuIdCmdMap MenuIdMap;
+
+extern HMENU hSubMenu;
+extern HINSTANCE g_hmodThisDll;
+
+void AddMenuList(int idCmd, std::string name)
+{
+ TDEBUG_TRACE("AddMenuList: idCmd = " << idCmd << " name = " << name);
+ MenuIdMap[idCmd] = MenuDescMap[name];
+}
+
+void InitMenuMaps()
+{
+ if (MenuDescMap.empty())
+ {
+ int sz = sizeof(menuDescList) / sizeof(MenuDescription);
+ for (int i=0; i < sz; i++)
+ {
+ MenuDescription md = menuDescList[i];
+ TDEBUG_TRACE("InitMenuMaps: adding " << md.name);
+ MenuDescMap[md.name] = md;
+ }
+ }
+
+ MenuIdMap.clear();
+}
+
+void InsertMenuItemWithIcon(HMENU hMenu, int indexMenu, int idCmd,
+ std::string menuText, std::string iconName)
+{
+ MENUITEMINFO mi;
+ mi.cbSize = sizeof(mi);
+ mi.dwTypeData = const_cast<char*> (menuText.c_str());
+ mi.cch = static_cast<UINT> (menuText.length());
+ mi.wID = idCmd;
+ mi.fType = MFT_STRING;
+
+ HICON h = GetTortoiseIcon(iconName);
+ if (h)
+ {
+ mi.fMask = MIIM_STRING | MIIM_FTYPE | MIIM_ID | MIIM_BITMAP | MIIM_DATA;
+ mi.dwItemData = (ULONG_PTR) h;
+ mi.hbmpItem = HBMMENU_CALLBACK;
+ }
+ else
+ {
+ TDEBUG_TRACE(" InsertMenuItemWithIcon: can't find " + iconName);
+ mi.fMask = MIIM_TYPE | MIIM_ID;
+ }
+ InsertMenuItem(hMenu, indexMenu, TRUE, &mi);
+}
+
+void InsertSubMenuItemWithIcon(HMENU hMenu, HMENU hSubMenu, int indexMenu, int idCmd,
+ std::string menuText, std::string iconName)
+{
+ MENUITEMINFO mi;
+ mi.cbSize = sizeof(mi);
+ mi.fMask = MIIM_SUBMENU | MIIM_STRING | MIIM_ID;
+ mi.fType = MFT_STRING;
+ mi.dwTypeData = const_cast<char*> (menuText.c_str());
+ mi.cch = static_cast<UINT> (menuText.length());
+ mi.wID = idCmd;
+ mi.hSubMenu = hSubMenu;
+ HICON h = GetTortoiseIcon(iconName);
+ if (h)
+ {
+ mi.fMask = MIIM_FTYPE | MIIM_STRING | MIIM_SUBMENU | MIIM_ID |
+ MIIM_BITMAP | MIIM_DATA;
+ mi.dwItemData = (ULONG_PTR) h;
+ mi.hbmpItem = HBMMENU_CALLBACK;
+ }
+ else
+ {
+ TDEBUG_TRACE(" InsertSubMenuItemWithIcon: can't find " + iconName);
+ }
+ InsertMenuItem(hMenu, indexMenu, TRUE, &mi);
+}
+
+void InsertMenuItemByName(HMENU hMenu, std::string name, int indexMenu,
+ int idCmd, int idCmdFirst)
+{
+ TDEBUG_TRACE("InsertMenuItemByName: name = " << name);
+ MenuDescriptionMap::iterator iter = MenuDescMap.find(name);
+ if (iter == MenuDescMap.end())
+ {
+ TDEBUG_TRACE("InsertMenuItemByName: can't find menu info for " << name);
+ return;
+ }
+
+ MenuDescription md = MenuDescMap[name];
+ AddMenuList(idCmd - idCmdFirst, name);
+ InsertMenuItemWithIcon(hMenu, indexMenu, idCmd, md.menuText, md.iconName);
+}
+
+// IContextMenu
+STDMETHODIMP
+CShellExt::QueryContextMenu(HMENU hMenu, UINT indexMenu, UINT idCmdFirst,
+ UINT idCmdLast, UINT uFlags)
+{
+ TDEBUG_TRACE("CShellExt::QueryContextMenu");
+ InitMenuMaps();
+
+ UINT idCmd = idCmdFirst;
+ BOOL bAppendItems = TRUE;
+
+ if((uFlags & 0x000F) == CMF_NORMAL)
+ bAppendItems = TRUE;
+ else if (uFlags & CMF_VERBSONLY)
+ bAppendItems = TRUE;
+ else if (uFlags & CMF_EXPLORE)
+ bAppendItems = TRUE;
+ else
+ bAppendItems = FALSE;
+
+ if (!bAppendItems)
+ return NOERROR;
+
+ // check if target directory is a Mercurial repository
+ bool isHgrepo = false;
+ std::string cwd;
+ if (!myFolder.empty())
+ {
+ cwd = myFolder;
+ }
+ else if (!myFiles.empty())
+ {
+ cwd = IsDirectory(myFiles[0])? myFiles[0] : DirName(myFiles[0]);
+ }
+ if (!cwd.empty())
+ isHgrepo = IsHgRepo(cwd);
+
+ // start building TortoiseHg menus and submenus
+ InsertMenu(hMenu, indexMenu, MF_SEPARATOR | MF_BYPOSITION, 0, NULL);
+ indexMenu++;
+
+ if (isHgrepo)
+ InsertMenuItemByName(hMenu, "commit", indexMenu++, idCmd++, idCmdFirst);
+
+ TDEBUG_TRACE(" CShellExt::QueryContextMenu: adding sub menus");
+ HMENU hSubMenu = CreatePopupMenu();
+ int indexSubMenu = 0;
+ if(hSubMenu)
+ {
+ if (isHgrepo)
+ {
+ InsertMenuItemByName(hSubMenu, "status", indexSubMenu++, idCmd++, idCmdFirst);
+
+ InsertMenu(hSubMenu, indexSubMenu++, MF_SEPARATOR | MF_BYPOSITION,
+ 0, NULL);
+ InsertMenuItemByName(hSubMenu, "log", indexSubMenu++, idCmd++, idCmdFirst);
+
+ InsertMenu(hSubMenu, indexSubMenu++, MF_SEPARATOR | MF_BYPOSITION,
+ 0, NULL);
+ InsertMenuItemByName(hSubMenu, "update", indexSubMenu++, idCmd++, idCmdFirst);
+
+ InsertMenu(hSubMenu, indexSubMenu++, MF_SEPARATOR | MF_BYPOSITION,
+ 0, NULL);
+ InsertMenuItemByName(hSubMenu, "synch", indexSubMenu++, idCmd++, idCmdFirst);
+ InsertMenuItemByName(hSubMenu, "recover", indexSubMenu++, idCmd++, idCmdFirst);
+ InsertMenuItemByName(hSubMenu, "serve", indexSubMenu++, idCmd++, idCmdFirst);
+
+ InsertMenu(hSubMenu, indexSubMenu++, MF_SEPARATOR | MF_BYPOSITION,
+ 0, NULL);
+ InsertMenuItemByName(hSubMenu, "userconf", indexSubMenu++, idCmd++, idCmdFirst);
+ }
+
+ InsertMenuItemByName(hSubMenu, "repoconf", indexSubMenu++, idCmd++, idCmdFirst);
+
+ InsertMenu(hSubMenu, indexSubMenu++, MF_SEPARATOR | MF_BYPOSITION,
+ 0, NULL);
+
+ InsertMenuItemByName(hSubMenu, "about", indexSubMenu++, idCmd++, idCmdFirst);
+ }
+
+ TDEBUG_TRACE(" CShellExt::QueryContextMenu: adding main THG menu");
+ InsertSubMenuItemWithIcon(hMenu, hSubMenu, indexMenu++, idCmd++,
+ "TortoiseHG...", "hg.ico");
+
+ InsertMenu(hMenu, indexMenu++, MF_SEPARATOR | MF_BYPOSITION, 0, NULL);
+
+ return ResultFromShort(idCmd - idCmdFirst);
+}
+
+STDMETHODIMP
+CShellExt::InvokeCommand(LPCMINVOKECOMMANDINFO lpcmi)
+{
+ TDEBUG_TRACE("CShellExt::InvokeCommand");
+
+ HRESULT hr = E_INVALIDARG;
+ if (!HIWORD(lpcmi->lpVerb))
+ {
+ UINT idCmd = LOWORD(lpcmi->lpVerb);
+ TDEBUG_TRACE("CShellExt::InvokeCommand: idCmd = " << idCmd);
+ MenuIdCmdMap::iterator iter = MenuIdMap.find(idCmd);
+ if(iter != MenuIdMap.end())
+ {
+ MenuAction action = MenuIdMap[idCmd].action;
+ hr = CALL_MEMBER_FN(*this, action)(lpcmi->hwnd, lpcmi->lpDirectory,
+ lpcmi->lpVerb, lpcmi->lpParameters, lpcmi->nShow);
+ }
+ else
+ {
+ TDEBUG_TRACE("CShellExt::InvokeCommand: action not found for idCmd " << idCmd);
+ }
+ }
+ return hr;
+}
+
+STDMETHODIMP
+CShellExt::GetCommandString(UINT idCmd, UINT uFlags, UINT FAR *reserved,
+ LPSTR pszName, UINT cchMax)
+{
+ TDEBUG_TRACE("CShellExt::GetCommandString");
+
+ *pszName = 0;
+ char *psz;
+
+ TDEBUG_TRACE("CShellExt::GetCommandString: idCmd = " << idCmd);
+ MenuIdCmdMap::iterator iter = MenuIdMap.find(idCmd);
+ if (iter != MenuIdMap.end())
+ {
+ TDEBUG_TRACE("CShellExt::GetCommandString: name = " << MenuIdMap[idCmd].name);
+ psz = (char*)MenuIdMap[idCmd].helpText.c_str();
+ }
+ else
+ {
+ TDEBUG_TRACE("CShellExt::GetCommandString: can't find idCmd " << idCmd);
+ psz = "";
+ }
+
+ wcscpy((wchar_t*)pszName, _WCSTR(psz));
+ return NOERROR;
+}
+
+STDMETHODIMP CShellExt::HandleMenuMsg(UINT uMsg, WPARAM wParam, LPARAM lParam)
+{
+ LRESULT res;
+ return HandleMenuMsg2(uMsg, wParam, lParam, &res);
+}
+
+STDMETHODIMP CShellExt::HandleMenuMsg2(UINT uMsg, WPARAM wParam, LPARAM lParam, LRESULT* pResult)
+{
+ TDEBUG_ENTER("CShellExt::HandleMenuMsg2");
+ // A great tutorial on owner drawn menus in shell extension can be found
+ // here: http://www.codeproject.com/shell/shellextguide7.asp
+
+ LRESULT res;
+ if (!pResult)
+ pResult = &res;
+ *pResult = FALSE;
+
+ switch (uMsg)
+ {
+ case WM_MEASUREITEM:
+ {
+ MEASUREITEMSTRUCT* lpmis = (MEASUREITEMSTRUCT*)lParam;
+ if (lpmis==NULL)
+ break;
+ lpmis->itemWidth += 2;
+ if(lpmis->itemHeight < 16)
+ lpmis->itemHeight = 16;
+ *pResult = TRUE;
+ }
+ break;
+ case WM_DRAWITEM:
+ {
+ DRAWITEMSTRUCT* lpdis = (DRAWITEMSTRUCT*)lParam;
+ if (!lpdis || (lpdis->CtlType != ODT_MENU) || !lpdis->itemData)
+ break; //not for a menu
+ DrawIconEx(lpdis->hDC,
+ lpdis->rcItem.left - 16,
+ lpdis->rcItem.top + (lpdis->rcItem.bottom - lpdis->rcItem.top - 16) / 2,
+ (HICON) lpdis->itemData, 16, 16,
+ 0, 0, DI_NORMAL);
+ *pResult = TRUE;
+ }
+ break;
+ default:
+ return NOERROR;
+ }
+
+ return NOERROR;
+}
|
|
@@ -0,0 +1,32 @@ + // TortoiseCVS - a Windows shell extension for easy version control
+
+// Copyright (C) 2003 - Hartmut Honisch
+// <Hartmut_Honisch@web.de> - November 2003
+
+// This program is free software; you can redistribute it and/or
+// modify it under the terms of the GNU General Public License
+// as published by the Free Software Foundation; either version 2
+// of the License, or (at your option) any later version.
+
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+
+// You should have received a copy of the GNU General Public License
+// along with this program; if not, write to the Free Software
+// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+#ifndef FIX_WIN_DEFS_H
+#define FIX_WIN_DEFS_H
+
+#undef SetPort
+#undef FindWindow
+#undef CreateDialog
+#undef GetCharWidth
+#undef GetWindowStyle
+#undef IsMaximized
+#undef GetUsername
+#undef min
+#undef max
+
+#endif /* FIX_WIN_DEFS_H */
|
|
@@ -0,0 +1,78 @@ + #include "stdafx.h"
+#include "ShellExt.h"
+#include "TortoiseUtils.h"
+#include "StringUtils.h"
+#include "PipeUtils.h"
+
+STDMETHODIMP CShellExt::GetOverlayInfo(LPWSTR pwszIconFile, int cchMax,
+ int *pIndex, DWORD *pdwFlags)
+{
+ *pIndex = 0;
+ *pdwFlags = ISIOI_ICONFILE;
+
+ // get installation path
+ std::string dir = GetTHgProgRoot();
+ if (dir.empty())
+ {
+ TDEBUG_TRACE("GetOverlayInfo: THG root is empty");
+ wcsncpy(pwszIconFile, L"", cchMax);
+ return S_OK;
+ }
+
+ // find icon per overlay type
+ std::wstring dirWide = MultibyteToWide(dir);
+ wcsncpy(pwszIconFile, dirWide.c_str(), cchMax);
+ cchMax -= static_cast<int>(dirWide.size()) + 1;
+/*
+ switch (myTortoiseClass)
+ {
+ case TORTOISE_OLE_ADDED:
+ wcsncat(pwszIconFile, L"\\icons\\status\\added.ico", cchMax);
+ break;
+ case TORTOISE_OLE_MODIFIED:
+ wcsncat(pwszIconFile, L"\\icons\\status\\changed.ico", cchMax);
+ break;
+ case TORTOISE_OLE_UNCHANGED:
+ wcsncat(pwszIconFile, L"\\icons\\status\\unchanged.ico", cchMax);
+ break;
+ default:
+ break;
+ }
+*/
+ std::string path = WideToMultibyte(pwszIconFile);
+ TDEBUG_TRACE("GetOverlayInfo: icon path = " << path);
+
+ return S_OK;
+}
+
+STDMETHODIMP CShellExt::GetPriority(int *pPriority)
+{
+ *pPriority = 1;
+ return S_OK;
+}
+
+#define BUFSIZE 512
+
+STDMETHODIMP CShellExt::IsMemberOf(LPCWSTR pwszPath, DWORD /* dwAttrib */)
+{
+ TCHAR status[BUFSIZE] = TEXT("");
+ int bufsize = BUFSIZE * sizeof(TCHAR);
+ std::string mbstr = WideToMultibyte(pwszPath);
+
+ TDEBUG_TRACE("IsMemberOf: search for " << mbstr.c_str());
+ int cbRead = query_pipe(mbstr.c_str(), status, bufsize);
+
+ if (cbRead < 0)
+ return S_FALSE;
+ else if (myTortoiseClass == TORTOISE_OLE_ADDED &&
+ strcmp(status, "added") == 0)
+ return S_OK;
+ else if (myTortoiseClass == TORTOISE_OLE_MODIFIED &&
+ strcmp(status, "modified") == 0)
+ return S_OK;
+ else if (myTortoiseClass == TORTOISE_OLE_UNCHANGED &&
+ strcmp(status, "unchanged") == 0)
+ return S_OK;
+
+ return S_FALSE;
+}
|
|
@@ -0,0 +1,33 @@ + DLLNAME=THgShell.dll
+
+OBJECTS = ContextMenu.o \
+ IconOverlay.o \
+ MenuActions.o \
+ ShellExt.o \
+ TortoiseUtils.o \
+ PipeUtils.o \
+ ShellUtils2.o \
+ StringUtils.o
+
+DEFFILE=ShellExt.def
+
+LDFLAGS=-L/lib -lole32 -lkernel32 -luser32 -lgdi32 -lshlwapi \
+ -lwininet -lwinmm -luuid \
+ -Wl,--subsystem,windows,--enable-stdcall-fixup,$(DEFFILE) \
+ -mwindows -shared
+
+# set DEBUG env var to 1 to enable debug trace
+ifeq ($(DEBUG),1)
+CXXFLAGS+=-D_DEBUG
+endif
+
+all: PipeUtils $(DLLNAME)
+
+$(DLLNAME): $(OBJECTS)
+ g++ -o $@ $(OBJECTS) $(LDFLAGS)
+
+PipeUtils: PipeUtils.cpp PipeUtils.h StringUtils.o TortoiseUtils.o
+ g++ -o $@ $(CXXFLAGS) -DAPPMAIN $< StringUtils.o TortoiseUtils.o
+
+clean:
+ rm -f *.o *.dll *.exe
|
|
|
@@ -0,0 +1,149 @@ + #include "stdafx.h"
+#include "ShellExt.h"
+#include "TortoiseUtils.h"
+#include "StringUtils.h"
+
+#include <stdio.h>
+#include <vector>
+
+void CShellExt::DoHgProc(const std::string &cmd, bool nofiles, bool nogui)
+{
+ std::string dir = GetTHgProgRoot();
+ TDEBUG_TRACE("DoHgProc: THG root = " << dir);
+ if (dir.empty())
+ {
+ TDEBUG_TRACE("DoHgProc: THG root is empty");
+ return;
+ }
+ std::string hgcmd = Quote(dir + "\\hgproc.bat") + " --command " + cmd;
+
+ if (nogui)
+ hgcmd += " --nogui";
+
+ std::string cwd;
+ std::vector<std::string> filelist;
+ if (!myFolder.empty())
+ {
+ cwd = myFolder;
+ filelist.push_back(GetHgRepoRoot(myFolder));
+ }
+ else if (!myFiles.empty())
+ {
+ cwd = IsDirectory(myFiles[0])? myFiles[0] : DirName(myFiles[0]);
+ filelist = myFiles;
+ }
+ else
+ {
+ TDEBUG_TRACE("DoHgProc: can't get cwd");
+ return;
+ }
+
+ hgcmd += " --cwd " + Quote(cwd);
+ hgcmd += " --root " + Quote(GetHgRepoRoot(cwd));
+
+ if (!nofiles)
+ {
+ std::string tempfile = GetTemporaryFile();
+ SECURITY_ATTRIBUTES sa;
+ memset(&sa, 0, sizeof(sa));
+ sa.nLength = sizeof(sa);
+ sa.bInheritHandle = TRUE;
+
+ TDEBUG_TRACE("DoHgProc: temp file = " << tempfile);
+ HANDLE tempfileHandle = CreateFileA(tempfile.c_str(), GENERIC_WRITE,
+ FILE_SHARE_READ, &sa, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, 0);
+
+ for (int i=0; i<filelist.size(); i++)
+ {
+ DWORD dwWritten;
+ TDEBUG_TRACE("DoHgProc: temp file adding " << filelist[i]);
+ WriteFile(tempfileHandle, filelist[i].c_str(),
+ static_cast<DWORD>(filelist[i].size()), &dwWritten, 0);
+ }
+ CloseHandle(tempfileHandle);
+ hgcmd += " --listfile " + Quote(tempfile);
+ hgcmd += " --deletelistfile" ;
+ }
+
+ LaunchCommand(hgcmd);
+}
+
+STDMETHODIMP
+CShellExt::CM_Commit(HWND hParent, LPCSTR pszWorkingDir, LPCSTR pszCmd,
+ LPCSTR pszParam, int iShowCmd)
+{
+ DoHgProc("commit");
+ return NOERROR;
+}
+
+STDMETHODIMP
+CShellExt::CM_Status(HWND hParent, LPCSTR pszWorkingDir, LPCSTR pszCmd,
+ LPCSTR pszParam, int iShowCmd)
+{
+ DoHgProc("status");
+ return NOERROR;
+}
+
+STDMETHODIMP
+CShellExt::CM_Log(HWND hParent, LPCSTR pszWorkingDir, LPCSTR pszCmd,
+ LPCSTR pszParam, int iShowCmd)
+{
+ DoHgProc("log");
+ return NOERROR;
+}
+
+STDMETHODIMP
+CShellExt::CM_About(HWND hParent, LPCSTR pszWorkingDir, LPCSTR pszCmd,
+ LPCSTR pszParam, int iShowCmd)
+{
+ DoHgProc("about");
+ return NOERROR;
+}
+
+STDMETHODIMP
+CShellExt::CM_Synch(HWND hParent, LPCSTR pszWorkingDir, LPCSTR pszCmd,
+ LPCSTR pszParam, int iShowCmd)
+{
+ DoHgProc("synch");
+ return NOERROR;
+}
+
+STDMETHODIMP
+CShellExt::CM_Serve(HWND hParent, LPCSTR pszWorkingDir, LPCSTR pszCmd,
+ LPCSTR pszParam, int iShowCmd)
+{
+ DoHgProc("serve");
+ return NOERROR;
+}
+
+STDMETHODIMP
+CShellExt::CM_Update(HWND hParent, LPCSTR pszWorkingDir, LPCSTR pszCmd,
+ LPCSTR pszParam, int iShowCmd)
+{
+ DoHgProc("update");
+ return NOERROR;
+}
+
+STDMETHODIMP
+CShellExt::CM_Recover(HWND hParent, LPCSTR pszWorkingDir, LPCSTR pszCmd,
+ LPCSTR pszParam, int iShowCmd)
+{
+ DoHgProc("recovery");
+ return NOERROR;
+}
+
+STDMETHODIMP
+CShellExt::CM_Userconf(HWND hParent, LPCSTR pszWorkingDir, LPCSTR pszCmd,
+ LPCSTR pszParam, int iShowCmd)
+{
+ DoHgProc("config", true);
+ return NOERROR;
+}
+
+STDMETHODIMP
+CShellExt::CM_Repoconf(HWND hParent, LPCSTR pszWorkingDir, LPCSTR pszCmd,
+ LPCSTR pszParam, int iShowCmd)
+{
+ DoHgProc("config");
+ return NOERROR;
+}
|
|
@@ -0,0 +1,95 @@ + #include "stdafx.h"
+#include "PipeUtils.h"
+#include "StringUtils.h"
+#include "TortoiseUtils.h"
+#include <stdio.h>
+#include <conio.h>
+#include <tchar.h>
+#include <wchar.h>
+
+LPTSTR lpszPipename = TEXT("\\\\.\\pipe\\PyPipeService");
+
+#define BUFSIZE 512
+
+int query_pipe(LPCSTR cstr, TCHAR *chReadBuf, int bufsize)
+{
+ BOOL fSuccess;
+ DWORD cbRead;
+
+ int outlen = (lstrlen((TCHAR*)cstr))*sizeof(TCHAR);
+ TDEBUG_TRACE("sending " << outlen << " bytes to pipe: " << cstr);
+
+ fSuccess = CallNamedPipe(
+ lpszPipename, // pipe name
+ (void *)cstr, // message to server
+ outlen, // message length
+ chReadBuf, // buffer to receive reply
+ bufsize, // size of read buffer
+ &cbRead, // number of bytes read
+ NMPWAIT_NOWAIT); // waits for 0 seconds
+
+ if (fSuccess || GetLastError() == ERROR_MORE_DATA)
+ {
+ TDEBUG_TRACE("receive " << cbRead << " bytes from pipe: " << chReadBuf);
+ return cbRead;
+ }
+ else
+ {
+ return -1;
+ }
+}
+
+int _test_pipe(LPCSTR lpszWrite)
+{
+ TCHAR readBuf[BUFSIZE] = TEXT("");
+ int bufsize = BUFSIZE*sizeof(TCHAR);
+ int cbRead = query_pipe(lpszWrite, readBuf, bufsize);
+
+ if (cbRead >= 0)
+ {
+ _tprintf( TEXT("read: %s\n"), readBuf );
+ }
+ else
+ {
+ _tprintf( TEXT("error calling pipe\n") );
+ }
+}
+
+#ifdef APPMAIN
+int _tmain(int argc, TCHAR *argv[])
+{
+ LPTSTR lpszWrite = TEXT("");
+
+ if (argc < 2)
+ {
+ _tprintf(TEXT("usage: %s file1 file2 ...\n"), argv[0]);
+ return 1;
+ }
+
+ for (int i=1; i<argc; i++)
+ {
+ lpszWrite = argv[i];
+ _test_pipe(lpszWrite);
+ }
+ WCHAR file[] = L"C:\\hg\\hg-tortoise\\hgproc.py";
+ std::string mbstr = WideToMultibyte(file);
+ const char *cstr = mbstr.c_str();
+ _test_pipe(cstr);
+
+ std::string root = GetTHgProgRoot();
+ if (root != "")
+ {
+ _tprintf(TEXT("THG root = %s\n"), root.c_str() );
+ }
+ else
+ {
+ _tprintf(TEXT("THG root not found in registry\n"));
+ }
+
+ //LaunchCommand("notepad");
+ //LaunchCommand("D:\\Profiles\\r28629\\My Documents\\Mercurial\\repos\\hg-tortoise-dev\\dist\\hgproc.exe")
+ //LaunchCommand("\"D:\\Profiles\\r28629\\My Documents\\Mercurial\\repos\\hg-tortoise-namedpipe\\hgproc.bat\"");
+
+ return 0;
+}
+#endif
|
|
@@ -0,0 +1,6 @@ + #ifndef __NTServiceManager_PipeUtils_Defined__
+#define __NTServiceManager_PipeUtils_Defined__
+
+int query_pipe(LPCSTR lpszWrite, TCHAR *chReadBuf, int bufsize);
+
+#endif
|
|
|
@@ -0,0 +1,799 @@ +
+
+//#include "stdafx.h"
+#include <windows.h>
+#include <winreg.h>
+#include "Registry.h"
+
+#define CLASS_NAME_LENGTH 255
+
+/* IMPORTANT NOTES ABOUT CREGISTRY:
+
+ CRegistry never keeps a key open past the end of a function call.
+ This is incase the application crashes before the next call to close
+ the registry
+
+ INCLUDE FILES
+ "winreg.h" and "afxdisp.h" must be included in "stdafx.h"
+
+ KEY NAMES:
+ Key names must not begin with a \ and only absolute strings are accepted
+
+*/
+
+
+
+CRegistry::CRegistry()
+{
+ m_hRootKey = HKEY_CURRENT_USER;
+ m_bLazyWrite = TRUE;
+ m_nLastError = ERROR_SUCCESS;
+}
+
+CRegistry::~CRegistry()
+{
+ ClearKey();
+}
+
+
+BOOL CRegistry::ClearKey()
+{
+ /* Call CloseKey to write the current key to the registry and close the
+ key. An application should not keep keys open any longer than necessary.
+ Calling CloseKey when there is no current key has no effect.*/
+
+ m_strCurrentPath.Empty();
+ m_hRootKey = HKEY_CURRENT_USER;
+ m_bLazyWrite = TRUE;
+ return TRUE;
+}
+
+
+
+BOOL CRegistry::SetRootKey(HKEY hRootKey)
+{
+ // sets the root key
+ // make sure to set it to a valid key
+ if (hRootKey != HKEY_CLASSES_ROOT &&
+ hRootKey != HKEY_CURRENT_USER &&
+ hRootKey != HKEY_LOCAL_MACHINE &&
+ hRootKey != HKEY_USERS) return FALSE;
+
+ m_hRootKey = hRootKey;
+ return TRUE;
+}
+
+
+BOOL CRegistry::CreateKey(CString strKey)
+{
+ /* Use CreateKey to add a new key to the registry.
+ Key is the name of the key to create. Key must be
+ an absolute name. An absolute key
+ begins with a backslash (\) and is a subkey of
+ the root key. */
+
+ ASSERT(strKey[0] != '\\');
+ HKEY hKey;
+
+ DWORD dwDisposition = 0;
+
+ if (::RegCreateKeyEx(m_hRootKey, LPCTSTR(strKey), 0, NULL,
+ REG_OPTION_NON_VOLATILE, KEY_ALL_ACCESS, NULL, &hKey,
+ &dwDisposition) != ERROR_SUCCESS) return FALSE;
+
+ if (!m_bLazyWrite) ::RegFlushKey(hKey);
+ ::RegCloseKey(hKey);
+ m_strCurrentPath = strKey;
+ return TRUE;
+}
+
+
+BOOL CRegistry::DeleteKey(CString strKey)
+{
+ /* Call DeleteKey to remove a specified key and its associated data,
+ if any, from the registry. Returns FALSE is there are subkeys
+ Subkeys must be explicitly deleted by separate calls to DeleteKey.
+ DeleteKey returns True if key deletion is successful. On error,
+ DeleteKey returns False. */
+
+ // need to open the key first with RegOpenKeyEx
+ ASSERT(FALSE); // not yet implemented
+ ASSERT(strKey[0] != '\\');
+
+ if (!KeyExists(strKey)) return TRUE;
+ if (::RegDeleteKey(m_hRootKey, strKey) != ERROR_SUCCESS) return FALSE;
+ return TRUE;
+}
+
+
+
+BOOL CRegistry::DeleteValue(CString strName)
+{
+ /* Call DeleteValue to remove a specific data value
+ associated with the current key. Name is string
+ containing the name of the value to delete. Keys can contain
+ multiple data values, and every value associated with a key
+ has a unique name. */
+
+ ASSERT(m_strCurrentPath.GetLength() > 0);
+ HKEY hKey;
+ LONG lResult;
+
+ if (::RegOpenKeyEx(m_hRootKey, LPCTSTR(m_strCurrentPath), 0,
+ KEY_SET_VALUE, &hKey) != ERROR_SUCCESS) return FALSE;
+
+ lResult = ::RegDeleteValue(hKey, LPCTSTR(strName));
+ ::RegCloseKey(hKey);
+
+ if (lResult == ERROR_SUCCESS) return TRUE;
+ return FALSE;
+}
+
+
+int CRegistry::GetDataSize(CString strValueName)
+{
+ /* Call GetDataSize to determine the size, in bytes, of
+ a data value associated with the current key. ValueName
+ is a string containing the name of the data value to query.
+ On success, GetDataSize returns the size of the data value.
+ On failure, GetDataSize returns -1. */
+
+ HKEY hKey;
+ ASSERT(m_strCurrentPath.GetLength() > 0);
+ LONG lResult;
+
+ if (::RegOpenKeyEx(m_hRootKey, LPCTSTR(m_strCurrentPath), 0,
+ KEY_QUERY_VALUE, &hKey) != ERROR_SUCCESS) return -1;
+
+ DWORD dwSize = 1;
+ lResult = ::RegQueryValueEx(hKey, LPCTSTR(strValueName),
+ NULL, NULL, NULL, &dwSize);
+ ::RegCloseKey(hKey);
+
+ if (lResult != ERROR_SUCCESS) return -1;
+ return (int)dwSize;
+}
+
+DWORD CRegistry::GetDataType(CString strValueName)
+{
+ HKEY hKey;
+ ASSERT(m_strCurrentPath.GetLength() > 0);
+
+ m_nLastError = ::RegOpenKeyEx(m_hRootKey, LPCTSTR(m_strCurrentPath), 0,
+ KEY_QUERY_VALUE, &hKey);
+
+ if (m_nLastError != ERROR_SUCCESS) return 0;
+
+ DWORD dwType = 1;
+ m_nLastError = ::RegQueryValueEx(hKey, LPCTSTR(strValueName),
+ NULL, &dwType, NULL, NULL);
+ ::RegCloseKey(hKey);
+
+ if (m_nLastError == ERROR_SUCCESS) return dwType;
+
+ return 0;
+}
+
+
+
+int CRegistry::GetSubKeyCount()
+{
+ /* Call this function to determine the number of subkeys.
+ the function returns -1 on error */
+ HKEY hKey;
+ ASSERT(m_strCurrentPath.GetLength() > 0);
+
+ if (::RegOpenKeyEx(m_hRootKey, LPCTSTR(m_strCurrentPath), 0,
+ KEY_ALL_ACCESS, &hKey) != ERROR_SUCCESS) return -1;
+
+ LONG lResult;
+ DWORD dwSubKeyCount, dwValueCount, dwClassNameLength,
+ dwMaxSubKeyName, dwMaxValueName, dwMaxValueLength;
+ FILETIME ftLastWritten;
+
+ _TCHAR szClassBuffer[CLASS_NAME_LENGTH];
+
+ dwClassNameLength = CLASS_NAME_LENGTH;
+ lResult = ::RegQueryInfoKey(hKey, szClassBuffer, &dwClassNameLength,
+ NULL, &dwSubKeyCount, &dwMaxSubKeyName, NULL, &dwValueCount,
+ &dwMaxValueName, &dwMaxValueLength, NULL, &ftLastWritten);
+
+ ::RegCloseKey(hKey);
+ if (lResult != ERROR_SUCCESS) return -1;
+
+ return (int)dwSubKeyCount;
+}
+
+
+int CRegistry::GetValueCount()
+{
+ /* Call this function to determine the number of subkeys.
+ the function returns -1 on error */
+ HKEY hKey;
+ ASSERT(m_strCurrentPath.GetLength() > 0);
+
+ if (::RegOpenKeyEx(m_hRootKey, LPCTSTR(m_strCurrentPath), 0,
+ KEY_ALL_ACCESS, &hKey) != ERROR_SUCCESS) return -1;
+
+ LONG lResult;
+ DWORD dwSubKeyCount, dwValueCount, dwClassNameLength,
+ dwMaxSubKeyName, dwMaxValueName, dwMaxValueLength;
+ FILETIME ftLastWritten;
+
+ _TCHAR szClassBuffer[CLASS_NAME_LENGTH];
+
+ dwClassNameLength = CLASS_NAME_LENGTH;
+ lResult = ::RegQueryInfoKey(hKey, szClassBuffer, &dwClassNameLength,
+ NULL, &dwSubKeyCount, &dwMaxSubKeyName, NULL, &dwValueCount,
+ &dwMaxValueName, &dwMaxValueLength, NULL, &ftLastWritten);
+
+ ::RegCloseKey(hKey);
+ if (lResult != ERROR_SUCCESS) return -1;
+
+ return (int)dwValueCount;
+}
+
+
+BOOL CRegistry::KeyExists(CString strKey, HKEY hRootKey)
+{
+ /* Call KeyExists to determine if a key of a specified name exists.
+ Key is the name of the key for which to search. */
+
+ ASSERT(strKey[0] != '\\');
+ HKEY hKey;
+
+ if (hRootKey == NULL) hRootKey = m_hRootKey;
+
+ LONG lResult = ::RegOpenKeyEx(hRootKey, LPCTSTR(strKey), 0,
+ KEY_ALL_ACCESS, &hKey);
+ ::RegCloseKey(hKey);
+ if (lResult == ERROR_SUCCESS) return TRUE;
+ return FALSE;
+}
+
+BOOL CRegistry::SetKey(CString strKey, BOOL bCanCreate)
+{
+ /* Call SetKey to make a specified key the current key. Key is the
+ name of the key to open. If Key is null, the CurrentKey property
+ is set to the key specified by the RootKey property.
+
+ CanCreate specifies whether to create the specified key if it does
+ not exist. If CanCreate is True, the key is created if necessary.
+
+ Key is opened or created with the security access value KEY_ALL_ACCESS.
+ OpenKey only creates non-volatile keys, A non-volatile key is stored in
+ the registry and is preserved when the system is restarted.
+
+ OpenKey returns True if the key is successfully opened or created */
+
+ ASSERT(strKey[0] != '\\');
+ HKEY hKey;
+
+
+ // close the current key if it is open
+ if (strKey.GetLength() == 0)
+ {
+ m_strCurrentPath.Empty();
+ return TRUE;
+ }
+
+ DWORD dwDisposition;
+ if (bCanCreate) // open the key with RegCreateKeyEx
+ {
+ if (::RegCreateKeyEx(m_hRootKey, LPCTSTR(strKey), 0, NULL,
+ REG_OPTION_NON_VOLATILE, KEY_ALL_ACCESS, NULL, &hKey,
+ &dwDisposition) != ERROR_SUCCESS) return FALSE;
+ m_strCurrentPath = strKey;
+ if (!m_bLazyWrite) ::RegFlushKey(hKey);
+ ::RegCloseKey(hKey);
+ return TRUE;
+ }
+
+ // otherwise, open the key without creating
+ // open key requires no initial slash
+ m_nLastError = ::RegOpenKeyEx(m_hRootKey, LPCTSTR(strKey), 0,
+ KEY_ALL_ACCESS, &hKey);
+ if (m_nLastError != ERROR_SUCCESS) return FALSE;
+ m_strCurrentPath = strKey;
+ if (!m_bLazyWrite) ::RegFlushKey(hKey);
+ ::RegCloseKey(hKey);
+ return TRUE;
+}
+
+
+BOOL CRegistry::ValueExists(CString strName)
+{
+ /* Call ValueExists to determine if a particular key exists in
+ the registry. Calling Value Exists is especially useful before
+ calling other TRegistry methods that operate only on existing keys.
+
+ Name is the name of the data value for which to check.
+ ValueExists returns True if a match if found, False otherwise. */
+
+ HKEY hKey;
+ LONG lResult;
+ ASSERT(m_strCurrentPath.GetLength() > 0);
+
+
+ if (::RegOpenKeyEx(m_hRootKey, LPCTSTR(m_strCurrentPath), 0,
+ KEY_ALL_ACCESS, &hKey) != ERROR_SUCCESS) return FALSE;
+
+ lResult = ::RegQueryValueEx(hKey, LPCTSTR(strName), NULL,
+ NULL, NULL, NULL);
+ ::RegCloseKey(hKey);
+
+ if (lResult == ERROR_SUCCESS) return TRUE;
+ return FALSE;
+}
+
+
+void CRegistry::RenameValue(CString strOldName, CString strNewName)
+{
+ /* Call RenameValue to change the name of a data value associated
+ with the current key. OldName is a string containing the current
+ name of the data value. NewName is a string containing the replacement
+ name for the data value.
+
+ If OldName is the name of an existing data value for the current key,
+ and NewName is not the name of an existing data value for the current
+ key, RenameValue changes the data value name as specified. Otherwise
+ the current name remains unchanged.
+ */
+ ASSERT(FALSE); // functionality not yet implemented
+}
+
+
+
+
+COleDateTime CRegistry::ReadDateTime(CString strName, COleDateTime dtDefault)
+{
+ /* Call ReadDate to read a date value from a specified data value
+ associated with the current key. Name is the name of the data value to read.
+ If successful, ReadDate returns a Delphi TDateTime value. The integral part
+ of a TDateTime value is the number of days that have passed since 12/30/1899.
+ The fractional part of a TDateTime value is the time of day.
+ On error, an exception is raised, and the value returned by this function
+ should be discarded. */
+
+ DWORD dwType = REG_BINARY;
+ COleDateTime dt;
+ DWORD dwSize = sizeof(dt);
+ HKEY hKey;
+
+ ASSERT(m_strCurrentPath.GetLength() > 0);
+ if (::RegOpenKeyEx(m_hRootKey, LPCTSTR(m_strCurrentPath), 0,
+ KEY_READ, &hKey) != ERROR_SUCCESS) return dtDefault;
+ if (::RegQueryValueEx(hKey, LPCTSTR(strName), NULL,
+ &dwType, (LPBYTE)&dt, &dwSize) != ERROR_SUCCESS) dt = dtDefault;
+ ::RegCloseKey(hKey);
+ return dt;
+}
+
+
+double CRegistry::ReadFloat(CString strName, double fDefault)
+{
+ /* Call ReadFloat to read a float value from a specified
+ data value associated with the current key. Name is the name
+ of the data value to read.
+
+ If successful, ReadFloat returns a double value.
+ On error, an exception is raised, and the value returned by
+ this function should be discarded. */
+
+ DWORD dwType = REG_BINARY;
+ double d;
+ DWORD dwSize = sizeof(d);
+ HKEY hKey;
+
+ ASSERT(m_strCurrentPath.GetLength() > 0);
+ if (::RegOpenKeyEx(m_hRootKey, LPCTSTR(m_strCurrentPath), 0,
+ KEY_READ, &hKey) != ERROR_SUCCESS) return fDefault;
+
+ if (::RegQueryValueEx(hKey, LPCTSTR(strName), NULL,
+ &dwType, (LPBYTE)&d, &dwSize) != ERROR_SUCCESS) d = fDefault;
+ ::RegCloseKey(hKey);
+ return d;
+}
+
+CString CRegistry::ReadString(CString strName, CString strDefault)
+{
+ DWORD dwType = REG_SZ;
+ DWORD dwSize = 255;
+ BOOL bSuccess = TRUE;
+ _TCHAR sz[255];
+ HKEY hKey;
+
+
+ ASSERT(m_strCurrentPath.GetLength() > 0);
+
+ // make sure it is the proper type
+ dwType = GetDataType(strName);
+
+ if (dwType != REG_SZ && dwType != REG_EXPAND_SZ)
+ {
+ return strDefault;
+ }
+
+ m_nLastError = ::RegOpenKeyEx(m_hRootKey, LPCTSTR(m_strCurrentPath), 0,
+ KEY_READ, &hKey);
+ if (m_nLastError != ERROR_SUCCESS) return strDefault;
+
+ m_nLastError = ::RegQueryValueEx(hKey, LPCTSTR(strName), NULL,
+ &dwType, (LPBYTE)sz, &dwSize);
+ if (m_nLastError != ERROR_SUCCESS) bSuccess = FALSE;
+ ::RegCloseKey(hKey);
+
+ if (!bSuccess) return strDefault;
+ return CString((LPCTSTR)sz);
+}
+
+DWORD CRegistry::ReadDword(CString strName, DWORD dwDefault)
+{
+ DWORD dwType = REG_DWORD;
+ DWORD dw;
+ DWORD dwSize = sizeof(dw);
+ HKEY hKey;
+
+ ASSERT(m_strCurrentPath.GetLength() > 0);
+ if (::RegOpenKeyEx(m_hRootKey, LPCTSTR(m_strCurrentPath), 0,
+ KEY_READ, &hKey) != ERROR_SUCCESS) return dwDefault;
+
+ if (::RegQueryValueEx(hKey, LPCTSTR(strName), NULL,
+ &dwType, (LPBYTE)&dw, &dwSize) != ERROR_SUCCESS) dw = dwDefault;
+ ::RegCloseKey(hKey);
+ return dw;
+}
+
+
+
+int CRegistry::ReadInt(CString strName, int nDefault)
+{
+ DWORD dwType = REG_BINARY;
+ int n;
+ DWORD dwSize = sizeof(n);
+ HKEY hKey;
+
+ ASSERT(m_strCurrentPath.GetLength() > 0);
+ if (::RegOpenKeyEx(m_hRootKey, LPCTSTR(m_strCurrentPath), 0,
+ KEY_READ, &hKey) != ERROR_SUCCESS) return nDefault;
+
+ if (::RegQueryValueEx(hKey, LPCTSTR(strName), NULL,
+ &dwType, (LPBYTE)&n, &dwSize) != ERROR_SUCCESS) n = nDefault;
+ ::RegCloseKey(hKey);
+ return n;
+}
+
+BOOL CRegistry::ReadBool(CString strName, BOOL bDefault)
+{
+ DWORD dwType = REG_BINARY;
+ BOOL b;
+ DWORD dwSize = sizeof(b);
+ HKEY hKey;
+
+ ASSERT(m_strCurrentPath.GetLength() > 0);
+ if (::RegOpenKeyEx(m_hRootKey, LPCTSTR(m_strCurrentPath), 0,
+ KEY_READ, &hKey) != ERROR_SUCCESS) return bDefault;
+
+ if (::RegQueryValueEx(hKey, LPCTSTR(strName), NULL,
+ &dwType, (LPBYTE)&b, &dwSize) != ERROR_SUCCESS) b = bDefault;
+ ::RegCloseKey(hKey);
+ return b;
+}
+
+
+COLORREF CRegistry::ReadColor(CString strName, COLORREF rgbDefault)
+{
+ DWORD dwType = REG_BINARY;
+ COLORREF rgb;
+ DWORD dwSize = sizeof(rgb);
+ HKEY hKey;
+
+ ASSERT(m_strCurrentPath.GetLength() > 0);
+ if (::RegOpenKeyEx(m_hRootKey, LPCTSTR(m_strCurrentPath), 0,
+ KEY_READ, &hKey) != ERROR_SUCCESS) return rgbDefault;
+
+ if (::RegQueryValueEx(hKey, LPCTSTR(strName), NULL,
+ &dwType, (LPBYTE)&rgb, &dwSize) != ERROR_SUCCESS) rgb = rgbDefault;
+ ::RegCloseKey(hKey);
+ return rgb;
+}
+
+BOOL CRegistry::ReadFont(CString strName, CFont* pFont)
+{
+ DWORD dwType = REG_BINARY;
+ DWORD dwSize = sizeof(LOGFONT);
+ BOOL bSuccess = TRUE;
+ HKEY hKey;
+ LOGFONT lf;
+
+ ASSERT(m_strCurrentPath.GetLength() > 0);
+ if (::RegOpenKeyEx(m_hRootKey, LPCTSTR(m_strCurrentPath), 0,
+ KEY_READ, &hKey) != ERROR_SUCCESS) return FALSE;
+
+ if (::RegQueryValueEx(hKey, LPCTSTR(strName), NULL,
+ &dwType, (LPBYTE)&lf, &dwSize) != ERROR_SUCCESS) bSuccess = FALSE;
+ ::RegCloseKey(hKey);
+ if (bSuccess)
+ {
+ pFont->Detach();
+ pFont->CreateFontIndirect(&lf);
+ }
+ return bSuccess;
+}
+
+
+BOOL CRegistry::ReadPoint(CString strName, CPoint* pPoint)
+{
+ DWORD dwType = REG_BINARY;
+ DWORD dwSize = sizeof(CPoint);
+ BOOL bSuccess = TRUE;
+ HKEY hKey;
+
+ ASSERT(m_strCurrentPath.GetLength() > 0);
+ if (::RegOpenKeyEx(m_hRootKey, LPCTSTR(m_strCurrentPath), 0,
+ KEY_READ, &hKey) != ERROR_SUCCESS) return FALSE;
+
+ if (::RegQueryValueEx(hKey, LPCTSTR(strName), NULL,
+ &dwType, (LPBYTE)pPoint, &dwSize) != ERROR_SUCCESS) bSuccess = FALSE;
+ ::RegCloseKey(hKey);
+ return bSuccess;
+}
+
+BOOL CRegistry::ReadSize(CString strName, CSize* pSize)
+{
+ DWORD dwType = REG_BINARY;
+ DWORD dwSize = sizeof(CSize);
+ BOOL bSuccess = TRUE;
+ HKEY hKey;
+
+ ASSERT(m_strCurrentPath.GetLength() > 0);
+ if (::RegOpenKeyEx(m_hRootKey, LPCTSTR(m_strCurrentPath), 0,
+ KEY_READ, &hKey) != ERROR_SUCCESS) return FALSE;
+
+ if (::RegQueryValueEx(hKey, LPCTSTR(strName), NULL,
+ &dwType, (LPBYTE)pSize, &dwSize) != ERROR_SUCCESS) bSuccess = FALSE;
+ ::RegCloseKey(hKey);
+ return bSuccess;
+}
+
+BOOL CRegistry::ReadRect(CString strName, CRect* pRect)
+{
+ DWORD dwType = REG_BINARY;
+ DWORD dwSize = sizeof(CRect);
+ BOOL bSuccess = TRUE;
+ HKEY hKey;
+
+ ASSERT(m_strCurrentPath.GetLength() > 0);
+ if (::RegOpenKeyEx(m_hRootKey, LPCTSTR(m_strCurrentPath), 0,
+ KEY_READ, &hKey) != ERROR_SUCCESS) return FALSE;
+
+ if (::RegQueryValueEx(hKey, LPCTSTR(strName), NULL,
+ &dwType, (LPBYTE)pRect, &dwSize) != ERROR_SUCCESS) bSuccess = FALSE;
+ ::RegCloseKey(hKey);
+ return bSuccess;
+}
+
+
+
+
+BOOL CRegistry::WriteBool(CString strName, BOOL bValue)
+{
+ ASSERT(m_strCurrentPath.GetLength() > 0);
+ BOOL bSuccess = TRUE;
+ HKEY hKey;
+
+ if (::RegOpenKeyEx(m_hRootKey, LPCTSTR(m_strCurrentPath), 0,
+ KEY_WRITE, &hKey) != ERROR_SUCCESS) return FALSE;
+
+ if (::RegSetValueEx(hKey, LPCTSTR(strName), 0,
+ REG_BINARY, (LPBYTE)&bValue, sizeof(bValue))
+ != ERROR_SUCCESS) bSuccess = FALSE;
+
+ if (!m_bLazyWrite) ::RegFlushKey(hKey);
+ ::RegCloseKey(hKey);
+ return bSuccess;
+}
+
+BOOL CRegistry::WriteDateTime(CString strName, COleDateTime dtValue)
+{
+ ASSERT(m_strCurrentPath.GetLength() > 0);
+ BOOL bSuccess = TRUE;
+ HKEY hKey;
+
+ if (::RegOpenKeyEx(m_hRootKey, LPCTSTR(m_strCurrentPath), 0,
+ KEY_WRITE, &hKey) != ERROR_SUCCESS) return FALSE;
+
+ if (::RegSetValueEx(hKey, LPCTSTR(strName), 0,
+ REG_BINARY, (LPBYTE)&dtValue, sizeof(dtValue))
+ != ERROR_SUCCESS) bSuccess = FALSE;
+
+ if (!m_bLazyWrite) ::RegFlushKey(hKey);
+ ::RegCloseKey(hKey);
+ return bSuccess;
+}
+
+
+BOOL CRegistry::WriteString(CString strName, CString strValue)
+{
+ ASSERT(m_strCurrentPath.GetLength() > 0);
+ BOOL bSuccess = TRUE;
+ HKEY hKey;
+ _TCHAR sz[255];
+
+ if (strValue.GetLength() > 254) return FALSE;
+
+#ifdef _UNICODE
+ wstrcpy(sz, LPCTSTR(strValue));
+#else
+ strcpy(sz, LPCTSTR(strValue));
+#endif
+
+ if (::RegOpenKeyEx(m_hRootKey, LPCTSTR(m_strCurrentPath), 0,
+ KEY_WRITE, &hKey) != ERROR_SUCCESS) return FALSE;
+
+#ifdef _UNICODE
+ if (::RegSetValueEx(hKey, LPCTSTR(strName), 0,
+ REG_SZ, (LPBYTE)sz, wstrlen(sz) + 1)
+ != ERROR_SUCCESS) bSuccess = FALSE;
+#else
+ if (::RegSetValueEx(hKey, LPCTSTR(strName), 0,
+ REG_SZ, (LPBYTE)sz, strlen(sz) + 1)
+ != ERROR_SUCCESS) bSuccess = FALSE;
+#endif
+
+ if (!m_bLazyWrite) ::RegFlushKey(hKey);
+ ::RegCloseKey(hKey);
+ return bSuccess;
+}
+
+
+BOOL CRegistry::WriteFloat(CString strName, double fValue)
+{
+ ASSERT(m_strCurrentPath.GetLength() > 0);
+ BOOL bSuccess = TRUE;
+ HKEY hKey;
+
+ if (::RegOpenKeyEx(m_hRootKey, LPCTSTR(m_strCurrentPath), 0,
+ KEY_WRITE, &hKey) != ERROR_SUCCESS) return FALSE;
+
+ if (::RegSetValueEx(hKey, LPCTSTR(strName), 0,
+ REG_BINARY, (LPBYTE)&fValue, sizeof(fValue))
+ != ERROR_SUCCESS) bSuccess = FALSE;
+
+ if (!m_bLazyWrite) ::RegFlushKey(hKey);
+ ::RegCloseKey(hKey);
+ return bSuccess;
+}
+
+BOOL CRegistry::WriteInt(CString strName, int nValue)
+{
+ ASSERT(m_strCurrentPath.GetLength() > 0);
+ BOOL bSuccess = TRUE;
+ HKEY hKey;
+
+ if (::RegOpenKeyEx(m_hRootKey, LPCTSTR(m_strCurrentPath), 0,
+ KEY_WRITE, &hKey) != ERROR_SUCCESS) return FALSE;
+
+ if (::RegSetValueEx(hKey, LPCTSTR(strName), 0,
+ REG_BINARY, (LPBYTE)&nValue, sizeof(nValue))
+ != ERROR_SUCCESS) bSuccess = FALSE;
+
+ if (!m_bLazyWrite) ::RegFlushKey(hKey);
+ ::RegCloseKey(hKey);
+ return bSuccess;
+}
+
+BOOL CRegistry::WriteDword(CString strName, DWORD dwValue)
+{
+ ASSERT(m_strCurrentPath.GetLength() > 0);
+ BOOL bSuccess = TRUE;
+ HKEY hKey;
+
+ if (::RegOpenKeyEx(m_hRootKey, LPCTSTR(m_strCurrentPath), 0,
+ KEY_WRITE, &hKey) != ERROR_SUCCESS) return FALSE;
+
+ if (::RegSetValueEx(hKey, LPCTSTR(strName), 0,
+ REG_BINARY, (LPBYTE)&dwValue, sizeof(dwValue))
+ != ERROR_SUCCESS) bSuccess = FALSE;
+
+ if (!m_bLazyWrite) ::RegFlushKey(hKey);
+ ::RegCloseKey(hKey);
+ return bSuccess;
+}
+
+BOOL CRegistry::WriteColor(CString strName, COLORREF rgbValue)
+{
+ ASSERT(m_strCurrentPath.GetLength() > 0);
+ BOOL bSuccess = TRUE;
+ HKEY hKey;
+
+ if (::RegOpenKeyEx(m_hRootKey, LPCTSTR(m_strCurrentPath), 0,
+ KEY_WRITE, &hKey) != ERROR_SUCCESS) return FALSE;
+
+ if (::RegSetValueEx(hKey, LPCTSTR(strName), 0,
+ REG_BINARY, (LPBYTE)&rgbValue, sizeof(rgbValue))
+ != ERROR_SUCCESS) bSuccess = FALSE;
+
+ if (!m_bLazyWrite) ::RegFlushKey(hKey);
+ ::RegCloseKey(hKey);
+ return bSuccess;
+}
+
+
+BOOL CRegistry::WriteFont(CString strName, CFont* pFont)
+{
+ ASSERT(m_strCurrentPath.GetLength() > 0);
+ BOOL bSuccess = TRUE;
+ HKEY hKey;
+
+ LOGFONT lf;
+ pFont->GetLogFont(&lf);
+
+ if (::RegOpenKeyEx(m_hRootKey, LPCTSTR(m_strCurrentPath), 0,
+ KEY_WRITE, &hKey) != ERROR_SUCCESS) return FALSE;
+
+ if (::RegSetValueEx(hKey, LPCTSTR(strName), 0,
+ REG_BINARY, (LPBYTE)&lf, sizeof(lf))
+ != ERROR_SUCCESS) bSuccess = FALSE;
+
+ if (!m_bLazyWrite) ::RegFlushKey(hKey);
+ ::RegCloseKey(hKey);
+ return bSuccess;
+}
+
+
+BOOL CRegistry::WritePoint(CString strName, CPoint* pPoint)
+{
+ ASSERT(m_strCurrentPath.GetLength() > 0);
+ BOOL bSuccess = TRUE;
+ HKEY hKey;
+
+ if (::RegOpenKeyEx(m_hRootKey, LPCTSTR(m_strCurrentPath), 0,
+ KEY_WRITE, &hKey) != ERROR_SUCCESS) return FALSE;
+
+ if (::RegSetValueEx(hKey, LPCTSTR(strName), 0,
+ REG_BINARY, (LPBYTE)pPoint, sizeof(CPoint))
+ != ERROR_SUCCESS) bSuccess = FALSE;
+
+ if (!m_bLazyWrite) ::RegFlushKey(hKey);
+ ::RegCloseKey(hKey);
+ return bSuccess;
+}
+
+
+BOOL CRegistry::WriteSize(CString strName, CSize* pSize)
+{
+ ASSERT(m_strCurrentPath.GetLength() > 0);
+ BOOL bSuccess = TRUE;
+ HKEY hKey;
+
+ if (::RegOpenKeyEx(m_hRootKey, LPCTSTR(m_strCurrentPath), 0,
+ KEY_WRITE, &hKey) != ERROR_SUCCESS) return FALSE;
+
+ if (::RegSetValueEx(hKey, LPCTSTR(strName), 0,
+ REG_BINARY, (LPBYTE)pSize, sizeof(CSize))
+ != ERROR_SUCCESS) bSuccess = FALSE;
+
+ if (!m_bLazyWrite) ::RegFlushKey(hKey);
+ ::RegCloseKey(hKey);
+ return bSuccess;
+}
+
+BOOL CRegistry::WriteRect(CString strName, CRect* pRect)
+{
+ ASSERT(m_strCurrentPath.GetLength() > 0);
+ BOOL bSuccess = TRUE;
+ HKEY hKey;
+
+ if (::RegOpenKeyEx(m_hRootKey, LPCTSTR(m_strCurrentPath), 0,
+ KEY_WRITE, &hKey) != ERROR_SUCCESS) return FALSE;
+
+ if (::RegSetValueEx(hKey, LPCTSTR(strName), 0,
+ REG_BINARY, (LPBYTE)pRect, sizeof(CRect))
+ != ERROR_SUCCESS) bSuccess = FALSE;
+
+ if (!m_bLazyWrite) ::RegFlushKey(hKey);
+ ::RegCloseKey(hKey);
+ return bSuccess;
+}
+
|
|
@@ -0,0 +1,77 @@ +
+
+#ifndef __REGISTRY_H__
+#define __REGISTRY_H__
+
+#include <string>
+typedef std::string CString;
+
+class CRegistry
+{
+public:
+ CRegistry();
+ ~CRegistry();
+
+int m_nLastError;
+
+// CRegistry properties
+protected:
+ HKEY m_hRootKey;
+ BOOL m_bLazyWrite;
+ CString m_strCurrentPath;
+
+public:
+ inline BOOL PathIsValid() {
+ return (m_strCurrentPath.GetLength() > 0); }
+ inline CString GetCurrentPath() {
+ return m_strCurrentPath; }
+ inline HKEY GetRootKey() {
+ return m_hRootKey; }
+
+
+//CRegistry methods
+public:
+ BOOL ClearKey();
+ BOOL SetRootKey(HKEY hRootKey);
+ BOOL CreateKey(CString strKey);
+ BOOL DeleteKey(CString strKey);
+ BOOL DeleteValue(CString strName);
+ int GetDataSize(CString strValueName);
+ DWORD GetDataType(CString strValueName);
+ int GetSubKeyCount();
+ int GetValueCount();
+ BOOL KeyExists(CString strKey, HKEY hRootKey = NULL);
+ BOOL SetKey(CString strKey, BOOL bCanCreate);
+ BOOL ValueExists(CString strName);
+ void RenameValue(CString strOldName, CString strNewName);
+
+ // data reading functions
+ COleDateTime ReadDateTime(CString strName, COleDateTime dtDefault);
+ double ReadFloat(CString strName, double fDefault);
+ CString ReadString(CString strName, CString strDefault);
+ int ReadInt(CString strName, int nDefault);
+ BOOL ReadBool(CString strName, BOOL bDefault);
+ COLORREF ReadColor(CString strName, COLORREF rgbDefault);
+ BOOL ReadFont(CString strName, CFont* pFont);
+ BOOL ReadPoint(CString strName, CPoint* pPoint);
+ BOOL ReadSize(CString strName, CSize* pSize);
+ BOOL ReadRect(CString strName, CRect* pRect);
+ DWORD ReadDword(CString strName, DWORD dwDefault);
+
+ // data writing functions
+ BOOL WriteBool(CString strName, BOOL bValue);
+ BOOL WriteDateTime(CString strName, COleDateTime dtValue);
+ BOOL WriteString(CString strName, CString strValue);
+ BOOL WriteFloat(CString strName, double fValue);
+ BOOL WriteInt(CString strName, int nValue);
+ BOOL WriteColor(CString strName, COLORREF rgbValue);
+ BOOL WriteFont(CString strName, CFont* pFont);
+ BOOL WritePoint(CString strName, CPoint* pPoint);
+ BOOL WriteSize(CString strName, CSize* pSize);
+ BOOL WriteRect(CString strName, CRect* pRect);
+ BOOL WriteDword(CString strName, DWORD dwValue);
+
+};// end of CRegistry class definition
+
+
+#endif
\ No newline at end of file |
|
|
@@ -0,0 +1,359 @@ + #include "stdafx.h"
+#include "ShellExt.h"
+#include "TortoiseUtils.h"
+#include "ShellUtils.h"
+#include "StringUtils.h"
+#include <olectl.h>
+
+DEFINE_GUID(CLSID_TortoiseHg0, 0xb456dba0L, 0x7bf4, 0x478c, 0x93, 0x7a, 0x5, 0x13, 0xc, 0x2c, 0x21, 0x2e);
+DEFINE_GUID(CLSID_TortoiseHg1, 0xb456dba1L, 0x7bf4, 0x478c, 0x93, 0x7a, 0x5, 0x13, 0xc, 0x2c, 0x21, 0x2e);
+DEFINE_GUID(CLSID_TortoiseHg2, 0xb456dba2L, 0x7bf4, 0x478c, 0x93, 0x7a, 0x5, 0x13, 0xc, 0x2c, 0x21, 0x2e);
+DEFINE_GUID(CLSID_TortoiseHg3, 0xb456dba3L, 0x7bf4, 0x478c, 0x93, 0x7a, 0x5, 0x13, 0xc, 0x2c, 0x21, 0x2e);
+DEFINE_GUID(CLSID_TortoiseHg4, 0xb456dba4L, 0x7bf4, 0x478c, 0x93, 0x7a, 0x5, 0x13, 0xc, 0x2c, 0x21, 0x2e);
+DEFINE_GUID(CLSID_TortoiseHg5, 0xb456dba5L, 0x7bf4, 0x478c, 0x93, 0x7a, 0x5, 0x13, 0xc, 0x2c, 0x21, 0x2e);
+DEFINE_GUID(CLSID_TortoiseHg6, 0xb456dba6L, 0x7bf4, 0x478c, 0x93, 0x7a, 0x5, 0x13, 0xc, 0x2c, 0x21, 0x2e);
+
+UINT g_cRefThisDll = 0;
+HINSTANCE g_hmodThisDll = NULL;
+
+HMENU hSubMenu = 0;
+
+typedef struct
+{
+ HKEY hRootKey;
+ LPTSTR lpszSubKey;
+ LPTSTR lpszValueName;
+ LPTSTR lpszData;
+} REGSTRUCT, *LPREGSTRUCT;
+
+VOID _LoadResources();
+VOID _UnloadResources();
+
+extern "C"
+int APIENTRY DllMain(HINSTANCE hInstance, DWORD dwReason, LPVOID lpReserved)
+{
+ TDEBUG_TRACE("DllMain");
+
+ if (dwReason == DLL_PROCESS_ATTACH)
+ {
+ g_hmodThisDll = hInstance;
+ _LoadResources();
+ }
+ else if (dwReason == DLL_PROCESS_DETACH)
+ _UnloadResources();
+
+ return 1;
+}
+
+STDAPI DllCanUnloadNow(void)
+{
+ TDEBUG_TRACE("DllCanUnloadNow");
+ return (g_cRefThisDll == 0 ? S_OK : S_FALSE);
+}
+
+STDAPI DllGetClassObject(REFCLSID rclsid, REFIID riid, LPVOID *ppvOut)
+{
+ LPWSTR pwszShellExt;
+ StringFromIID(rclsid, &pwszShellExt);
+ TDEBUG_TRACE("DllGetClassObject clsid = " << WideToMultibyte(pwszShellExt));
+ *ppvOut = NULL;
+
+ if (IsEqualIID(rclsid, CLSID_TortoiseHg0))
+ {
+ CDllRegSxClassFactory *pcf = new CDllRegSxClassFactory(TORTOISE_OLE_UNCHANGED);
+ TDEBUG_TRACE("DllGetClassObject clsname = " << "CLSID_TortoiseHg0");
+ return pcf->QueryInterface(riid, ppvOut);
+ }
+ else if (IsEqualIID(rclsid, CLSID_TortoiseHg1))
+ {
+ CDllRegSxClassFactory *pcf = new CDllRegSxClassFactory(TORTOISE_OLE_ADDED);
+ TDEBUG_TRACE("DllGetClassObject clsname = " << "CLSID_TortoiseHg1");
+ return pcf->QueryInterface(riid, ppvOut);
+ }
+ else if (IsEqualIID(rclsid, CLSID_TortoiseHg2))
+ {
+ CDllRegSxClassFactory *pcf = new CDllRegSxClassFactory(TORTOISE_OLE_MODIFIED);
+ TDEBUG_TRACE("DllGetClassObject clsname = " << "CLSID_TortoiseHg2");
+ return pcf->QueryInterface(riid, ppvOut);
+ }
+
+ return CLASS_E_CLASSNOTAVAILABLE;
+}
+
+VOID _LoadResources(VOID)
+{
+}
+
+VOID _UnloadResources(VOID)
+{
+ if (hSubMenu)
+ DestroyMenu(hSubMenu);
+}
+
+CDllRegSxClassFactory::CDllRegSxClassFactory(TortoiseOLEClass classToMake)
+{
+ m_cRef = 0L;
+ g_cRefThisDll++;
+ myclassToMake = classToMake;
+}
+
+CDllRegSxClassFactory::~CDllRegSxClassFactory()
+{
+ g_cRefThisDll--;
+}
+
+STDMETHODIMP
+CDllRegSxClassFactory::QueryInterface(REFIID riid, LPVOID FAR *ppv)
+{
+ *ppv = NULL;
+
+ if(IsEqualIID(riid, IID_IUnknown) || IsEqualIID(riid, IID_IClassFactory))
+ {
+ *ppv = (LPCLASSFACTORY)this;
+ AddRef();
+
+ return NOERROR;
+ }
+
+ return E_NOINTERFACE;
+}
+
+STDMETHODIMP_(ULONG)
+CDllRegSxClassFactory::AddRef()
+{
+ return ++m_cRef;
+}
+
+STDMETHODIMP_(ULONG)
+CDllRegSxClassFactory::Release()
+{
+ if (--m_cRef)
+ return m_cRef;
+
+ delete this;
+ return 0L;
+}
+
+STDMETHODIMP
+CDllRegSxClassFactory::CreateInstance(LPUNKNOWN pUnkOuter, REFIID riid, LPVOID *ppvObj)
+{
+ *ppvObj = NULL;
+
+ if (pUnkOuter)
+ return CLASS_E_NOAGGREGATION;
+
+ LPCSHELLEXT pShellExt = new CShellExt(myclassToMake);
+ if (NULL == pShellExt)
+ return E_OUTOFMEMORY;
+
+ return pShellExt->QueryInterface(riid, ppvObj);
+}
+
+STDMETHODIMP
+CDllRegSxClassFactory::LockServer(BOOL fLock)
+{
+ return NOERROR;
+}
+
+CShellExt::CShellExt(TortoiseOLEClass tortoiseClass)
+ : m_ppszFileUserClickedOn(0)
+{
+ myTortoiseClass = tortoiseClass;
+ m_cRef = 0L;
+ m_pDataObj = NULL;
+
+ g_cRefThisDll++;
+}
+
+CShellExt::~CShellExt()
+{
+ if (m_pDataObj)
+ m_pDataObj->Release();
+
+ g_cRefThisDll--;
+}
+
+STDMETHODIMP
+CShellExt::QueryInterface(REFIID riid, LPVOID FAR *ppv)
+{
+ std::string clsname = "UNKNOWN CLSID";
+
+ *ppv = NULL;
+ if (IsEqualIID(riid, IID_IShellExtInit) || IsEqualIID(riid, IID_IUnknown))
+ {
+ *ppv = (LPSHELLEXTINIT)this;
+ clsname = "IID_IShellExtInit";
+ }
+ else if (IsEqualIID(riid, IID_IContextMenu))
+ {
+ *ppv = (LPCONTEXTMENU)this;
+ clsname = "IID_IContextMenu";
+ }
+ else if (IsEqualIID(riid, IID_IContextMenu2))
+ {
+ *ppv = (IContextMenu2 *) this;
+ clsname = "IID_IContextMenu2";
+ }
+ else if (IsEqualIID(riid, IID_IContextMenu3))
+ {
+ *ppv = (IContextMenu3 *) this;
+ clsname = "IID_IContextMenu3";
+ }
+ else if (IsEqualIID(riid, IID_IShellIconOverlayIdentifier))
+ {
+ *ppv = (IShellIconOverlayIdentifier *) this;
+ clsname = "IID_IShellIconOverlayIdentifier";
+ }
+
+ TDEBUG_TRACE("CShellExt::QueryInterface: " << clsname);
+
+ if(*ppv)
+ {
+ AddRef();
+ return NOERROR;
+ }
+
+ return E_NOINTERFACE;
+}
+
+STDMETHODIMP_(ULONG)
+CShellExt::AddRef()
+{
+ return ++m_cRef;
+}
+
+STDMETHODIMP_(ULONG)
+CShellExt::Release()
+{
+ if(--m_cRef)
+ return m_cRef;
+
+ delete this;
+ return 0L;
+}
+
+#if 0
+STDMETHODIMP
+CShellExt::Initialize(LPCITEMIDLIST pIDFolder, LPDATAOBJECT pDataObj, HKEY hRegKey)
+{
+ if (m_pDataObj)
+ m_pDataObj->Release();
+ if (pDataObj)
+ {
+ m_pDataObj = pDataObj;
+ pDataObj->AddRef();
+ }
+ return NOERROR;
+}
+
+#else
+
+STDMETHODIMP
+CShellExt::Initialize(LPCITEMIDLIST pIDFolder, LPDATAOBJECT pDataObj, HKEY hRegKey)
+{
+ TCHAR name[MAX_PATH+1];
+
+ TDEBUG_TRACE("CShellExt::Initialize");
+ TDEBUG_TRACE(" pIDFolder: " << pIDFolder);
+ TDEBUG_TRACE(" pDataObj: " << pDataObj);
+
+ myFolder.clear();
+ myFiles.clear();
+
+ if (pDataObj)
+ {
+#if 1
+ FORMATETC fmt = { CF_HDROP, NULL, DVASPECT_CONTENT, -1, TYMED_HGLOBAL };
+ STGMEDIUM stg = { TYMED_HGLOBAL };
+ if (SUCCEEDED(pDataObj->GetData(&fmt, &stg)) && stg.hGlobal)
+ {
+ HDROP hDrop = (HDROP) GlobalLock(stg.hGlobal);
+
+ if (hDrop)
+ {
+ UINT uNumFiles = DragQueryFile(hDrop, 0xFFFFFFFF, NULL, 0);
+ TDEBUG_TRACE(" hDrop uNumFiles = " << uNumFiles);
+ for (int i = 0; i < uNumFiles; ++i) {
+ if (DragQueryFile(hDrop, i, name, MAX_PATH) > 0)
+ {
+ TDEBUG_TRACE(" DragQueryFile [" << i << "] = " << name);
+ myFiles.push_back(name);
+ }
+ }
+ }
+ else
+ {
+ TDEBUG_TRACE(" hDrop is NULL ");
+ }
+
+ GlobalUnlock(stg.hGlobal);
+ if (stg.pUnkForRelease)
+ {
+ IUnknown* relInterface = (IUnknown*) stg.pUnkForRelease;
+ relInterface->Release();
+ }
+ }
+ else
+ {
+ TDEBUG_TRACE(" pDataObj->GetData failed");
+ }
+
+#else
+
+ STGMEDIUM medium;
+ FORMATETC fmte = { RegisterClipboardFormat(CFSTR_SHELLIDLIST),
+ NULL, DVASPECT_CONTENT, -1, TYMED_HGLOBAL };
+ HRESULT hres = pDataObj->GetData(&fmte, &medium);
+
+ if (SUCCEEDED(hres) && medium.hGlobal)
+ {
+ // Enumerate PIDLs which the user has selected
+ CIDA* cida = (CIDA*) GlobalLock(medium.hGlobal);
+ LPCITEMIDLIST parentFolder = GetPIDLFolder(cida);
+ TDEBUG_TRACE("Parent folder: " << GetPathFromIDList(parentFolder));
+ int count = cida->cidl;
+ TDEBUG_TRACE("Selected items: " << count);
+ for (int i = 0; i < count; ++i)
+ {
+ LPCITEMIDLIST child = GetPIDLItem(cida, i);
+ LPITEMIDLIST absolute = AppendPIDL(parentFolder, child);
+ std::string name = GetPathFromIDList(absolute);
+ TDEBUG_TRACE("Processing " << GetPathFromIDList(absolute));
+ if (IsShortcut(absolute))
+ {
+ TDEBUG_TRACE("IsShortCut " << name);
+ LPITEMIDLIST target = GetShortcutTarget(absolute);
+ ItemListFree(absolute);
+ absolute = target;
+ name = GetPathFromIDList(target);
+ }
+
+ name = GetPathFromIDList(absolute);
+ TDEBUG_TRACE("myFiles pusing " << name);
+ myFiles.push_back(name);
+
+ ItemListFree(absolute);
+ }
+
+ GlobalUnlock(medium.hGlobal);
+ if (medium.pUnkForRelease)
+ {
+ IUnknown* relInterface = (IUnknown*) medium.pUnkForRelease;
+ relInterface->Release();
+ }
+ }
+#endif
+ }
+
+ // if a directory background
+ if (pIDFolder)
+ {
+ SHGetPathFromIDList(pIDFolder, name);
+ TDEBUG_TRACE(" Folder " << name);
+ myFolder = name;
+ }
+
+ return NOERROR;
+}
+
+#endif
|
|
@@ -0,0 +1,9 @@ + ; shellext: Declares the module parameters for the DLL.
+
+LIBRARY TORTOISEHGSHELL
+DESCRIPTION 'Shell Extensions for TortoiseHg'
+
+EXPORTS
+ DllCanUnloadNow PRIVATE
+ DllGetClassObject PRIVATE
+
|
|
|
@@ -0,0 +1,112 @@ + #ifndef _SHELL_EXT_H_
+#define _SHELL_EXT_H_
+
+#pragma data_seg(".text")
+#include <objbase.h>
+#define INITGUID
+#include <initguid.h>
+#include <shlobj.h>
+#include <shlguid.h>
+#include <vector>
+#include <string>
+#pragma data_seg()
+
+#define DLLREGUNREGNAME TEXT("DLL Registerer")
+
+enum TortoiseOLEClass
+{
+ TORTOISE_OLE_INVALID,
+ TORTOISE_OLE_ADDED,
+ TORTOISE_OLE_MODIFIED,
+ TORTOISE_OLE_UNCHANGED,
+ TORTOISE_OLE_IGNORED,
+ TORTOISE_OLE_NOTINREPO,
+};
+
+//
+// Factory
+//
+class CDllRegSxClassFactory : public IClassFactory
+{
+ protected:
+ ULONG m_cRef;
+ TortoiseOLEClass myclassToMake;
+
+ public:
+ CDllRegSxClassFactory(TortoiseOLEClass);
+ ~CDllRegSxClassFactory();
+
+ public:
+ STDMETHODIMP QueryInterface(REFIID, LPVOID FAR *);
+ STDMETHODIMP_(ULONG) AddRef();
+ STDMETHODIMP_(ULONG) Release();
+
+ STDMETHODIMP CreateInstance(LPUNKNOWN, REFIID, LPVOID FAR *);
+ STDMETHODIMP LockServer(BOOL);
+};
+
+typedef CDllRegSxClassFactory *LPCSHELLEXTCLASSFACTORY;
+
+//
+// Shell extensions
+//
+class CShellExt :
+ public
+ IContextMenu3,
+ IShellIconOverlayIdentifier,
+ IShellExtInit
+{
+ TortoiseOLEClass myTortoiseClass;
+
+ protected:
+ ULONG m_cRef;
+ LPDATAOBJECT m_pDataObj;
+
+ LPTSTR *m_ppszFileUserClickedOn; // [MAX_PATH]
+ std::vector<std::string> myFiles;
+ std::string myFolder;
+
+ protected:
+ void CShellExt::DoHgProc(const std::string &, bool=false, bool=false);
+
+ public:
+ // context menu actions
+ STDMETHODIMP CM_Commit(HWND hParent, LPCSTR pszWorkingDir, LPCSTR pszCmd, LPCSTR pszParam, int iShowCmd);
+ STDMETHODIMP CM_Status(HWND hParent, LPCSTR pszWorkingDir, LPCSTR pszCmd, LPCSTR pszParam, int iShowCmd);
+ STDMETHODIMP CM_Log(HWND hParent, LPCSTR pszWorkingDir, LPCSTR pszCmd, LPCSTR pszParam, int iShowCmd);
+ STDMETHODIMP CM_About(HWND hParent, LPCSTR pszWorkingDir, LPCSTR pszCmd, LPCSTR pszParam, int iShowCmd);
+ STDMETHODIMP CM_Serve(HWND hParent, LPCSTR pszWorkingDir, LPCSTR pszCmd, LPCSTR pszParam, int iShowCmd);
+ STDMETHODIMP CM_Synch(HWND hParent, LPCSTR pszWorkingDir, LPCSTR pszCmd, LPCSTR pszParam, int iShowCmd);
+ STDMETHODIMP CM_Update(HWND hParent, LPCSTR pszWorkingDir, LPCSTR pszCmd, LPCSTR pszParam, int iShowCmd);
+ STDMETHODIMP CM_Recover(HWND hParent, LPCSTR pszWorkingDir, LPCSTR pszCmd, LPCSTR pszParam, int iShowCmd);
+ STDMETHODIMP CM_Userconf(HWND hParent, LPCSTR pszWorkingDir, LPCSTR pszCmd, LPCSTR pszParam, int iShowCmd);
+ STDMETHODIMP CM_Repoconf(HWND hParent, LPCSTR pszWorkingDir, LPCSTR pszCmd, LPCSTR pszParam, int iShowCmd);
+
+ public:
+ CShellExt(TortoiseOLEClass);
+ ~CShellExt();
+
+ // IUnknown
+ STDMETHODIMP QueryInterface(REFIID riid, LPVOID FAR *ppv);
+ STDMETHODIMP_(ULONG) AddRef();
+ STDMETHODIMP_(ULONG) Release();
+
+ // IContextMenu3
+ STDMETHODIMP QueryContextMenu(HMENU hMenu, UINT indexMenu, UINT idCmdFirst, UINT idCmdLast, UINT uFlags);
+ STDMETHODIMP InvokeCommand(LPCMINVOKECOMMANDINFO lpcmi);
+ STDMETHODIMP GetCommandString(UINT idCmd, UINT uFlags, UINT FAR *reserved, LPSTR pszName, UINT cchMax);
+ STDMETHODIMP HandleMenuMsg(UINT uMsg, WPARAM wParam, LPARAM lParam);
+ STDMETHODIMP HandleMenuMsg2(UINT uMsg, WPARAM wParam, LPARAM lParam, LRESULT *pResult);
+
+ // IShellIconOverlayIdentifier
+ STDMETHODIMP GetOverlayInfo(LPWSTR pwszIconFile, int cchMax, int *pIndex, DWORD *pdwFlags);
+ STDMETHODIMP GetPriority(int *pPriority);
+ STDMETHODIMP IsMemberOf(LPCWSTR pwszPath, DWORD dwAttrib);
+
+ // IShellExtInit
+ STDMETHODIMP Initialize(LPCITEMIDLIST pIDFolder, LPDATAOBJECT pDataObj, HKEY hKeyID);
+ };
+
+typedef CShellExt *LPCSHELLEXT;
+
+#endif // _SHELL_EXT_H_
|
This file's diff was not loaded because this changeset is very large. Load changes Loading... |
|
|
@@ -0,0 +1,128 @@ + // TortoiseCVS - a Windows shell extension for easy version control
+
+// Copyright (C) 2000 - Francis Irving
+// <francis@flourish.org> - May 2000
+
+// This program is free software; you can redistribute it and/or
+// modify it under the terms of the GNU General Public License
+// as published by the Free Software Foundation; either version 2
+// of the License, or (at your option) any later version.
+
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+
+// You should have received a copy of the GNU General Public License
+// along with this program; if not, write to the Free Software
+// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+
+#ifndef SHELL_UTILS_H
+#define SHELL_UTILS_H
+
+#include <windows.h>
+#include "FixWinDefs.h"
+#include <shlobj.h>
+#include <string>
+#include <vector>
+
+
+// Explorer pidl data structure walking functions.
+// These are probably compatible with Borland builder ones
+// of the same name (judging by usenet posting snippets).
+// _Who_ invented this stuff in an API? Madness.
+LPCITEMIDLIST GetNextItem(LPCITEMIDLIST pidl);
+int GetItemCount(LPCITEMIDLIST pidl);
+UINT GetSize(LPCITEMIDLIST pidl);
+LPITEMIDLIST DuplicateItem(LPMALLOC pMalloc, LPCITEMIDLIST pidl);
+// And some more found from usenet, ported from Delphi...
+bool IsDesktopFolder(LPCITEMIDLIST pidl);
+LPITEMIDLIST AppendPIDL(LPCITEMIDLIST dest, LPCITEMIDLIST src);
+// And more...
+void ItemListFree(LPITEMIDLIST pidl);
+bool IsEqualPIDL(LPCITEMIDLIST a, LPCITEMIDLIST b); // this possibly doesn't work at all, test it when you try to use it
+std::string DisplayNamePIDL(LPCITEMIDLIST pidl);
+
+// From "Shell Clipboard Formats" in the MSDN library:
+// << The following two macros can be used to retrieve PIDLs from a CIDA structure.
+// The first takes a pointer to the structure and retrieves the PIDL of the parent folder.
+// The second takes a pointer to the structure and retrieves one of the other PIDLs,
+// identified by its zero-based index. >>
+#define GetPIDLFolder(pida) (LPCITEMIDLIST)(((LPBYTE)pida)+(pida)->aoffset[0])
+#define GetPIDLItem(pida, i) (LPCITEMIDLIST)(((LPBYTE)pida)+(pida)->aoffset[i+1])
+
+// Launch a command, optionally wait for termination
+bool LaunchCommand(const std::string& command, bool waitForEnd, bool minimized = false);
+
+// Return true if it is safe to view this file, i.e. it is not an executable
+bool FileIsViewable(const std::string& filename);
+
+// Launch a file to be opened by the registered type in the shell
+bool LaunchFile(const std::string& filename, bool waitForEnd);
+
+std::string DesktopFolder();
+
+// Path of special folder
+std::string GetSpecialFolder(int nFolder);
+
+// Test if PIDL points to a special folder
+bool IsSpecialFolder(LPCITEMIDLIST pidl, int nFolder);
+
+// Get path from IDList
+std::string GetPathFromIDList(LPCITEMIDLIST pidl);
+
+// Strips the last ID from the list
+LPITEMIDLIST StripLastID(LPCITEMIDLIST pidl);
+
+// Get the last ID from the list
+LPITEMIDLIST GetLastID(LPCITEMIDLIST pidl);
+
+// Bind to parent
+IShellFolder* BindToParent(LPCITEMIDLIST pidl);
+
+// Is PIDL a shortcut
+bool IsShortcut(LPCITEMIDLIST pidl);
+
+// Get target of a shortcut
+LPITEMIDLIST GetShortcutTarget(LPCITEMIDLIST pidl);
+
+// Clone a PIDL
+LPITEMIDLIST CloneIDList(LPCITEMIDLIST pidl);
+
+
+// Rebuild icons
+bool RebuildIcons();
+
+// Notify shell of change
+void ShellNotifyUpdateFile(const std::string& sFilename);
+
+// Notify shell of change
+void ShellNotifyUpdateFiles(const std::string& sDirname,
+ const std::vector<std::string>& sFilenames);
+
+// Notify shell of change
+void ShellNotifyUpdateFiles(const std::vector<std::string>& sFilenames);
+
+void ShellNotifyUpdateDir(const std::string& sDirname);
+
+// Wait while processing messages
+DWORD WaitWithMsgQueue(DWORD nCount, const HANDLE* pHandles, bool fWaitAll,
+ DWORD dwMilliseconds);
+
+// Get path for iconset
+std::string GetIconSetPath(const std::string& iconSet);
+
+// Get name of iconset
+wxString GetIconSetName(const std::string& iconSet);
+
+// Get attributes for file (contains bugfix for SHGetFileInfo)
+BOOL ShellGetFileAttributes(const char* filename, DWORD *attr);
+
+// Get attributes for file (contains bugfix for SHGetFileInfo)
+BOOL ShellGetFileAttributesPidl(LPCITEMIDLIST pidl, DWORD *attr);
+
+// Get icon size
+BOOL ShellGetIconSize(UINT iconsize, int *width, int *height);
+
+
+#endif
|
|
|
@@ -0,0 +1,366 @@ + // TortoiseCVS - a Windows shell extension for easy version control
+
+// Copyright (C) 2001 - Francis Irving
+// <francis@flourish.org> - May 2001
+
+// This program is free software; you can redistribute it and/or
+// modify it under the terms of the GNU General Public License
+// as published by the Free Software Foundation; either version 2
+// of the License, or (at your option) any later version.
+
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+
+// You should have received a copy of the GNU General Public License
+// along with this program; if not, write to the Free Software
+// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+
+
+#include "StdAfx.h"
+#include "ShellUtils.h"
+#include "StringUtils.h"
+
+
+// We don't use SHGetSpecialFolderPath as older versions
+// of Windows NT don't support it.
+std::string GetSpecialFolder(int nFolder)
+{
+ HRESULT hr;
+ LPITEMIDLIST pidl = 0;
+ std::string result;
+ hr = SHGetSpecialFolderLocation(NULL, nFolder, &pidl);
+ if (FAILED(hr))
+ goto Cleanup;
+
+ result = GetPathFromIDList(pidl);
+
+Cleanup:
+ if (pidl)
+ ItemListFree(pidl);
+ return result;
+}
+
+
+void ItemListFree(LPITEMIDLIST pidl)
+{
+ if ( pidl )
+ {
+ LPMALLOC pMalloc;
+ SHGetMalloc(&pMalloc);
+ if ( pMalloc )
+ {
+ pMalloc->Free(pidl);
+ pMalloc->Release();
+ }
+ else
+ {
+ ASSERT(false);
+ }
+ }
+}
+
+
+// Get path from IDList
+std::string GetPathFromIDList(LPCITEMIDLIST pidl)
+{
+ std::string result;
+ static char dir[MAX_PATH + 1];
+
+ if(SHGetPathFromIDListA(pidl, dir))
+ result = dir;
+ return result;
+}
+
+
+// Is PIDL a shortcut
+bool IsShortcut(LPCITEMIDLIST pidl)
+{
+ TDEBUG_ENTER("IsShortcut");
+ DWORD dwAttributes = SFGAO_LINK;
+ if (ShellGetFileAttributesPidl(pidl, &dwAttributes))
+ {
+ if (dwAttributes & SFGAO_LINK)
+ {
+ TDEBUG_TRACE("return true");
+ return true;
+ }
+ }
+ TDEBUG_TRACE("return false");
+ return false;
+}
+
+
+// Get target of a shortcut
+LPITEMIDLIST GetShortcutTarget(LPCITEMIDLIST pidl)
+{
+ HRESULT hr;
+ IShellLink *pShLink = 0;
+ IPersistFile *ppf = 0;
+ std::wstring wsPath;
+ LPITEMIDLIST pidlResult = 0;
+
+ // If it's not a shortcut, exit
+ if (!IsShortcut(pidl))
+ {
+ pidlResult = CloneIDList(pidl);
+ goto Cleanup;
+ }
+
+ // get path of shortcut
+ wsPath = MultibyteToWide(GetPathFromIDList(pidl));
+
+ hr = CoCreateInstance(CLSID_ShellLink, NULL, CLSCTX_INPROC_SERVER,
+ IID_IShellLink, (LPVOID*) &pShLink);
+
+ if (FAILED(hr))
+ goto Cleanup;
+
+ hr = pShLink->QueryInterface(IID_IPersistFile, (LPVOID*) &ppf);
+ if (FAILED(hr))
+ goto Cleanup;
+
+ hr = ppf->Load(wsPath.c_str(), STGM_READ);
+ if (FAILED(hr))
+ goto Cleanup;
+
+
+ hr = pShLink->Resolve(GetDesktopWindow(), SLR_NO_UI);
+ if (FAILED(hr))
+ goto Cleanup;
+
+ hr = pShLink->GetIDList(&pidlResult);
+ if (FAILED(hr))
+ goto Cleanup;
+
+Cleanup:
+ if (pShLink)
+ pShLink->Release();
+
+ if (ppf)
+ ppf->Release();
+
+ return pidlResult;
+}
+
+
+// Returns the concatination of the two PIDLs. Neither passed PIDLs are
+// freed so it is up to the caller to free them.
+LPITEMIDLIST AppendPIDL(LPCITEMIDLIST dest, LPCITEMIDLIST src)
+{
+ LPMALLOC pMalloc;
+ if (!SUCCEEDED(SHGetMalloc(&pMalloc)))
+ return NULL;
+
+ int destSize = 0;
+ int srcSize = 0;
+
+ // Appending a PIDL to the DesktopPIDL is invalid so don't allow it.
+ if (dest != NULL && !IsDesktopFolder(dest))
+ destSize = GetSize(dest) - sizeof(dest->mkid.cb);
+
+ if (src != NULL)
+ srcSize = GetSize(src);
+
+ LPITEMIDLIST sum = (LPITEMIDLIST)pMalloc->Alloc(destSize + srcSize);
+ if (sum != NULL)
+ {
+ if (dest != NULL)
+ CopyMemory((char*)sum, dest, destSize);
+ if (src != NULL)
+ CopyMemory((char*)sum + destSize, src, srcSize);
+ }
+
+ pMalloc->Release();
+ return sum;
+}
+
+
+// Get attributes for file (contains bugfix for SHGetFileInfo)
+BOOL MyShellGetFileAttr(const void* data, DWORD *attr, bool bIsPidl)
+{
+ TDEBUG_ENTER("MyShellGetFileAttr");
+#ifndef UNICODE
+ // Workaround for NT4 bug: SHGetFileInfoA doesn't work correclty,
+ // so use SHGetFileInfoW
+
+ if (WindowsVersionIsNT4())
+ {
+ TDEBUG_TRACE("Windows NT4 workaround");
+ SHFILEINFOW fi;
+ std::wstring ws;
+ DWORD dwFlags = SHGFI_ATTRIBUTES;
+ if (attr == 0)
+ {
+ SetLastError(ERROR_INVALID_PARAMETER);
+ return false;
+ }
+ if (*attr != 0)
+ {
+ TDEBUG_TRACE("Attributes: " << *attr);
+ fi.dwAttributes = *attr;
+ dwFlags |= SHGFI_ATTR_SPECIFIED;
+ }
+ if (bIsPidl)
+ {
+ TDEBUG_TRACE("It's a PIDL");
+ dwFlags |= SHGFI_PIDL;
+ }
+ else
+ {
+ TDEBUG_TRACE("It's a path:" << (const char *) data);
+ ws = MultibyteToWide((const char *) data, 0);
+ data = ws.c_str();
+ }
+
+ DWORD dwResult = SHGetFileInfoW((LPWSTR) data, 0, &fi, sizeof(fi),
+ dwFlags);
+ *attr = fi.dwAttributes;
+ return (dwResult != 0);
+ }
+#endif
+
+ SHFILEINFOA fi;
+ DWORD dwFlags = SHGFI_ATTRIBUTES;
+ if (attr != 0)
+ {
+ fi.dwAttributes = *attr;
+ dwFlags |= SHGFI_ATTR_SPECIFIED;
+ }
+ if (bIsPidl)
+ dwFlags |= SHGFI_PIDL;
+
+ DWORD dwResult = SHGetFileInfoA((LPCSTR) data, 0, &fi, sizeof(fi), dwFlags);
+ *attr = fi.dwAttributes;
+ return (dwResult != 0);
+}
+
+
+// Get attributes for file (contains bugfix for SHGetFileInfo)
+BOOL ShellGetFileAttributes(const char* filename, DWORD *attr)
+{
+ return MyShellGetFileAttr(filename, attr, false);
+}
+
+
+// Get attributes for file (contains bugfix for SHGetFileInfo)
+BOOL ShellGetFileAttributesPidl(LPCITEMIDLIST pidl, DWORD *attr)
+{
+ return MyShellGetFileAttr(pidl, attr, true);
+}
+
+
+// Tests the passed PIDL to see if it is the root Desktop Folder
+bool IsDesktopFolder(LPCITEMIDLIST pidl)
+{
+ if (pidl != NULL)
+ return pidl->mkid.cb == 0;
+ else
+ return false;
+}
+
+
+bool IsEqualPIDL(LPCITEMIDLIST a, LPCITEMIDLIST b)
+{
+ UINT asiz = GetSize(a);
+ UINT bsiz = GetSize(b);
+ if (asiz != bsiz)
+ return false;
+
+ if (memcmp(a, b, asiz) == 0)
+ return true;
+
+ return false;
+}
+
+LPCITEMIDLIST GetNextItem(LPCITEMIDLIST pidl)
+{
+ if (pidl == NULL)
+ return NULL;
+
+ // Get size of the item identifier we are on
+ int cb = pidl->mkid.cb;
+
+ // If zero, then end of list
+ if (cb == 0)
+ return NULL;
+
+ // Move on
+ pidl = (LPITEMIDLIST) (((LPBYTE)pidl) + cb);
+
+ // Return NULL if null-terminating, or pidl otherwise
+ return (pidl->mkid.cb == 0) ? NULL : (LPITEMIDLIST) pidl;
+}
+
+int GetItemCount(LPCITEMIDLIST pidl)
+{
+ int count = 0;
+
+ while (pidl != 0)
+ {
+ count++;
+ pidl = GetNextItem(pidl);
+ }
+
+ return count;
+}
+
+UINT GetSize(LPCITEMIDLIST pidl)
+{
+ UINT total = 0;
+ if (pidl)
+ {
+ total += sizeof(pidl->mkid.cb);
+ while (pidl)
+ {
+ total += pidl->mkid.cb;
+ pidl = GetNextItem(pidl);
+ }
+ }
+ return total;
+}
+
+LPITEMIDLIST DuplicateItem(LPMALLOC pMalloc, LPCITEMIDLIST pidl)
+{
+ int cb = pidl->mkid.cb;
+ if (cb == 0)
+ return NULL;
+
+ LPITEMIDLIST pidlRet = (LPITEMIDLIST)pMalloc->Alloc(cb + sizeof(USHORT));
+ if (pidlRet == NULL)
+ return NULL;
+
+ CopyMemory(pidlRet, pidl, cb);
+ *((USHORT*) (((LPBYTE)pidlRet) + cb)) = 0;
+ return pidlRet;
+}
+
+
+// Clone a PIDL
+LPITEMIDLIST CloneIDList(LPCITEMIDLIST pidl)
+{
+ LPITEMIDLIST pidlResult = 0;
+ DWORD dwSize;
+ LPMALLOC pMalloc;
+
+ if (!SUCCEEDED(SHGetMalloc(&pMalloc)))
+ goto Cleanup;
+
+ dwSize = GetSize(pidl);
+ if (dwSize == 0)
+ goto Cleanup;
+
+ pidlResult = (LPITEMIDLIST) pMalloc->Alloc(dwSize);
+ if (!pidlResult)
+ goto Cleanup;
+
+ CopyMemory(pidlResult, pidl, dwSize);
+
+Cleanup:
+ if (pMalloc)
+ pMalloc->Release();
+
+ return pidlResult;
+}
+
|
This file's diff was not loaded because this changeset is very large. Load changes Loading... |
|
|
@@ -0,0 +1,150 @@ + // TortoiseCVS - a Windows shell extension for easy version control
+
+// Copyright (C) 2002 - Francis Irving
+// <francis@flourish.org> - May 2002
+
+// This program is free software; you can redistribute it and/or
+// modify it under the terms of the GNU General Public License
+// as published by the Free Software Foundation; either version 2
+// of the License, or (at your option) any later version.
+
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+
+// You should have received a copy of the GNU General Public License
+// along with this program; if not, write to the Free Software
+// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+
+#ifndef _STRING_UTILS_H
+#define _STRING_UTILS_H
+
+#include <string>
+//#include <wx/string.h>
+#include <vector>
+#include <map>
+#include <windows.h>
+//#include "FixWinDefs.h"
+
+
+#ifdef _MSC_VER
+ // Fancier GUI Visual C++ asserts
+ #include <crtdbg.h>
+#else
+ // Standard C assert
+ #include <assert.h>
+#ifndef _ASSERT
+ #define _ASSERT assert
+#endif
+
+ // This seems needed by Borland and GCC.
+ // Who else? What standard is it?
+ #include <errno.h>
+ #ifndef ENOMEM
+ #define ENOMEM 12
+ #endif
+#endif
+
+#ifndef ASSERT
+ #define ASSERT _ASSERT
+#endif
+
+// From: http://www.kbcafe.com/articles/cplusplus.tricks.html
+template<class T> void FindAndReplace(T& source, const T& find, const T& replace)
+{
+ size_t j;
+ for (j = 0; (j = source.find(find, j)) != T::npos;)
+ {
+ source.replace(j, find.length(), replace);
+ j += replace.length();
+ }
+}
+
+// Return the length of the longest string in the vector.
+int MaxStringLength(const std::vector<std::string>& stringvec);
+
+void MakeLowerCase(std::string& s);
+
+void MakeUpperCase(std::string& s);
+
+// Remove leading whitespaces from a string
+std::string TrimLeft(const std::string& str);
+
+
+// Remove trailing whitespaces from a string
+std::string TrimRight(const std::string& str);
+
+
+// Remove leading and trailing whitespaces from a string
+std::string Trim(const std::string& str);
+
+// Test if string starts with substr
+bool StartsWith(const std::string& str, const std::string& substr);
+
+// Quotes a string
+std::string Quote(const std::string& str);
+
+// Cuts the first token off a delimited list
+std::string CutFirstToken(std::string& sList, const std::string sDelimiter);
+
+// Printf returning a std::string
+//wxString Printf(const wxChar* format, ...);
+
+std::string PrintfA(const char* format, ...);
+
+// Convert Unicode string to multibyte string
+std::string WideToMultibyte(const std::wstring& wide, UINT CodePage = CP_ACP);
+
+// Convert multibyte string to Unicode string
+std::wstring MultibyteToWide(const std::string& multibyte, UINT CodePage = CP_ACP);
+
+#if wxUSE_UNICODE
+#define wxText(xxx) MultibyteToWide(xxx)
+#define wxTextCStr(xxx) MultibyteToWide(xxx).c_str()
+#define wxAscii(xxx) WideToMultibyte(xxx)
+#else
+#define wxText(xxx) xxx
+#define wxTextCStr(xxx) (xxx).c_str()
+#define wxAscii(xxx) xxx
+#endif
+
+// Serialize a vector of strings
+std::string SerializeStringVector(const std::vector<std::string>& vStrings,
+ const std::string& sDelimiter);
+
+// Expand environment strings
+std::string ExpandEnvStrings(const std::string& str);
+
+#if wxUSE_UNICODE
+wxString ExpandEnvStrings(const wxString& str);
+#endif
+
+// Replace parameters (%something)
+std::string ReplaceParams(const std::string& str,
+ const std::map<std::string, std::string> params);
+
+// comparison function object
+class less_nocase
+{
+public:
+ bool operator()(const std::string& x, const std::string& y) const
+ {
+ std::string::const_iterator p = x.begin();
+ std::string::const_iterator q = y.begin();
+
+ while (p != x.end() && q != y.end() && toupper(*p) == toupper(*q))
+ ++p, ++q;
+
+ if (p == x.end()) // Reached end of x: Return true if y is longer than x
+ return q != y.end();
+
+ if (q == y.end()) // Reached end of y, but not x, so x is longer than y
+ return false;
+
+ return toupper(*p) < toupper(*q);
+ }
+};
+
+
+#endif
|
|
@@ -0,0 +1,33 @@ + [Setup]
+AppCopyright=Copyright 2007 TK Soh and others
+AppName=TortoiseHg
+AppVerName=TortoiseHg snapshot
+;InfoAfterFile=iss/postinstall.txt
+;LicenseFile=COPYING.txt
+ShowLanguageDialog=yes
+AppPublisher=TK Soh and others
+AppPublisherURL=http://tortoisehg.sourceforge.net/
+AppSupportURL=http://tortoisehg.sourceforge.net/
+AppUpdatesURL=http://tortoisehg.sourceforge.net/
+AppID=TortoiseHg
+AppContact=teekaysoh@gmail.com
+OutputBaseFilename=THgShell_setup
+DefaultDirName={sd}\TortoiseHg
+;SourceDir=.
+VersionInfoDescription=TortoiseHg
+VersionInfoCopyright=Copyright 2007 TK Soh and others
+VersionInfoCompany=TK Soh and others
+InternalCompressLevel=max
+SolidCompression=true
+;SetupIconFile=icons\tortoise\hg.ico
+AllowNoIcons=true
+DefaultGroupName=TortoiseHg
+PrivilegesRequired=poweruser
+;AlwaysRestart=yes
+SetupLogging=yes
+
+[Files]
+Source: THgShell.dll; DestDir: {app}; Flags: ignoreversion
+Source: ..\..\icons\*; DestDir: {app}\icons ; Flags: ignoreversion recursesubdirs createallsubdirs
+
+#include "registry.iss"
|
This file's diff was not loaded because this changeset is very large. Load changes Loading... |
This file's diff was not loaded because this changeset is very large. Load changes Loading... |
This file's diff was not loaded because this changeset is very large. Load changes Loading... |
This file's diff was not loaded because this changeset is very large. Load changes Loading... |
Loading...