diff options
Diffstat (limited to 'catchcopy-windows-explorer-plugin')
-rwxr-xr-x | catchcopy-windows-explorer-plugin/CatchCopy.cpp | 115 | ||||
-rwxr-xr-x | catchcopy-windows-explorer-plugin/CatchCopy.def | 7 | ||||
-rwxr-xr-x | catchcopy-windows-explorer-plugin/CatchCopy.pro | 49 | ||||
-rwxr-xr-x | catchcopy-windows-explorer-plugin/ClassFactory.cpp | 84 | ||||
-rwxr-xr-x | catchcopy-windows-explorer-plugin/ClassFactory.h | 22 | ||||
-rwxr-xr-x | catchcopy-windows-explorer-plugin/ClientCatchcopy.cpp | 455 | ||||
-rwxr-xr-x | catchcopy-windows-explorer-plugin/ClientCatchcopy.h | 68 | ||||
-rwxr-xr-x | catchcopy-windows-explorer-plugin/DDShellExt.cpp | 188 | ||||
-rwxr-xr-x | catchcopy-windows-explorer-plugin/DDShellExt.h | 46 | ||||
-rwxr-xr-x | catchcopy-windows-explorer-plugin/Deque.cpp | 100 | ||||
-rwxr-xr-x | catchcopy-windows-explorer-plugin/Deque.h | 29 | ||||
-rwxr-xr-x | catchcopy-windows-explorer-plugin/Reg.cpp | 403 | ||||
-rwxr-xr-x | catchcopy-windows-explorer-plugin/Reg.h | 103 | ||||
-rwxr-xr-x | catchcopy-windows-explorer-plugin/Variable.h | 7 | ||||
-rwxr-xr-x | catchcopy-windows-explorer-plugin/resource.h | 18 |
15 files changed, 1694 insertions, 0 deletions
diff --git a/catchcopy-windows-explorer-plugin/CatchCopy.cpp b/catchcopy-windows-explorer-plugin/CatchCopy.cpp new file mode 100755 index 0000000..58d36fb --- /dev/null +++ b/catchcopy-windows-explorer-plugin/CatchCopy.cpp @@ -0,0 +1,115 @@ +// Implementation of DLL Exports.
+#include "resource.h"
+#include "DDShellExt.h"
+#include "ClassFactory.h"
+#include "Reg.h"
+
+#ifndef _M_X64
+const CLSID CLSID_DDShellExt = {0x68D44A27,0xFFB6,0x4B89,{0xA3,0xE5,0x7B,0x0E,0x50,0xA7,0xAB,0x33}};
+#else
+const CLSID CLSID_DDShellExt = {0x68ff37c4,0x51bc,0x4c2a,{0xa9,0x92,0x7e,0x39,0xbc,0xe,0x70,0x6f}};
+#endif
+
+HINSTANCE g_hInst = NULL;
+long g_cDllRef = 0;
+
+// DLL Entry Point
+extern "C" BOOL WINAPI DllMain(HINSTANCE hInstance, DWORD dwReason, LPVOID lpReserved)
+{
+ (void)lpReserved;
+ switch(dwReason){
+ case DLL_PROCESS_ATTACH:
+ //MessageBox ( NULL,L"DLL_PROCESS_ATTACH", L"DLL_PROCESS_ATTACH", MB_OK);
+ // Hold the instance of this DLL module, we will use it to get the
+ // path of the DLL to register the component.
+ g_hInst = hInstance;
+ DisableThreadLibraryCalls(hInstance);
+ break;
+ case DLL_PROCESS_DETACH:
+ //MessageBox ( NULL,L"DLL_PROCESS_DETACH", L"DLL_PROCESS_DETACH", MB_OK);
+ break;
+ }
+
+ return TRUE; //_AtlModule.DllMain(hInstance, dwReason, lpReserved,ObjectMap,NULL);
+}
+
+
+// Used to determine whether the DLL can be unloaded by OLE
+STDAPI DllCanUnloadNow(void)
+{
+ return g_cDllRef > 0 ? S_FALSE : S_OK;
+}
+
+
+// Returns a class factory to create an object of the requested type
+STDAPI DllGetClassObject(REFCLSID rclsid, REFIID riid, LPVOID* ppv)
+{
+ HRESULT hr = CLASS_E_CLASSNOTAVAILABLE;
+ if (IsEqualCLSID(CLSID_DDShellExt, rclsid))
+ {
+ hr = E_OUTOFMEMORY;
+ ClassFactory *pClassFactory = new ClassFactory();
+ if (pClassFactory)
+ {
+ hr = pClassFactory->QueryInterface(riid, ppv);
+ pClassFactory->Release();
+ }
+ }
+ return hr;
+}
+
+
+// DllRegisterServer - Adds entries to the system registry
+STDAPI DllRegisterServer(void)
+{
+// registers object, typelib and all interfaces in typelib
+
+ HRESULT hr;
+
+ wchar_t szModule[MAX_PATH];
+ if (GetModuleFileName(g_hInst, szModule, ARRAYSIZE(szModule)) == 0)
+ {
+ hr = HRESULT_FROM_WIN32(GetLastError());
+ return hr;
+ }
+ // Register the component.
+ hr = RegisterInprocServer(szModule, CLSID_DDShellExt, L"CatchCopy Class", L"Apartment");
+ if (SUCCEEDED(hr))
+ {
+ // Register the context menu handler. The context menu handler is
+ // associated with the * file class.
+ hr = RegisterShellExtContextMenuHandler(L"textfile", CLSID_DDShellExt, L"CatchCopy");
+ hr = RegisterShellExtContextMenuHandler(L"Drive", CLSID_DDShellExt, L"CatchCopy");
+ hr = RegisterShellExtContextMenuHandler(L"Directory", CLSID_DDShellExt, L"CatchCopy");
+ hr = RegisterShellExtContextMenuHandler(L"Folder", CLSID_DDShellExt, L"CatchCopy");
+ }
+ return hr;
+}
+
+
+// DllUnregisterServer - Removes entries from the system registry
+STDAPI DllUnregisterServer(void)
+{
+ m_ac.disconnectFromServer();
+ HRESULT hr = S_OK;
+
+ wchar_t szModule[MAX_PATH];
+ if (GetModuleFileName(g_hInst, szModule, ARRAYSIZE(szModule)) == 0)
+ {
+ hr = HRESULT_FROM_WIN32(GetLastError());
+ return hr;
+ }
+
+ // Unregister the component.
+ hr = UnregisterInprocServer(CLSID_DDShellExt);
+ if (SUCCEEDED(hr))
+ {
+ // Unregister the context menu handler.
+ hr = UnregisterShellExtContextMenuHandler(L"textfile", CLSID_DDShellExt);
+ hr = UnregisterShellExtContextMenuHandler(L"Drive", CLSID_DDShellExt);
+ hr = UnregisterShellExtContextMenuHandler(L"Directory", CLSID_DDShellExt);
+ hr = UnregisterShellExtContextMenuHandler(L"Folder", CLSID_DDShellExt);
+ return hr;
+ }
+ return S_OK;
+}
diff --git a/catchcopy-windows-explorer-plugin/CatchCopy.def b/catchcopy-windows-explorer-plugin/CatchCopy.def new file mode 100755 index 0000000..78582f4 --- /dev/null +++ b/catchcopy-windows-explorer-plugin/CatchCopy.def @@ -0,0 +1,7 @@ +LIBRARY "CatchCopy.DLL"
+
+EXPORTS
+ DllGetClassObject = DllGetClassObject@12
+ DllCanUnloadNow = DllCanUnloadNow@0
+ DllRegisterServer = DllRegisterServer@0
+ DllUnregisterServer = DllUnregisterServer@0
diff --git a/catchcopy-windows-explorer-plugin/CatchCopy.pro b/catchcopy-windows-explorer-plugin/CatchCopy.pro new file mode 100755 index 0000000..99dcd62 --- /dev/null +++ b/catchcopy-windows-explorer-plugin/CatchCopy.pro @@ -0,0 +1,49 @@ +QT -= core gui + +CONFIG += 64bit +CONFIG -= exceptions rtti + +#DEFINES += CATCHCOPY_EXPLORER_PLUGIN_DEBUG + +CONFIG(32bit) { + TARGET = catchcopy32 + QMAKE_CFLAGS = -march=i586 -m32 + QMAKE_CXXFLAGS = -march=i586 -m32 + QMAKE_LFLAGS += -m32 +} +CONFIG(64bit) { + TARGET = catchcopy64 + LIBS += -LC:\x86_64-4.9.3-release-win32-seh-rt_v4-rev1\mingw64\lib64 + DEFINES += _M_X64 + QMAKE_CFLAGS = -m64 + QMAKE_CXXFLAGS = -m64 + QMAKE_LFLAGS += -m64 +} + +QMAKE_CFLAGS -= -fexceptions -mthreads -O2 +QMAKE_CXXFLAGS -= -fexceptions -mthreads -O2 +QMAKE_CFLAGS += -std=c++98 -fno-keep-inline-dllexport -mtune=generic -fno-exceptions -Os -Wall -Wextra -fno-rtti -s -static -static-libgcc -static-libstdc++ +QMAKE_CXXFLAGS += -std=c++98 -fno-keep-inline-dllexport -mtune=generic -fno-exceptions -Os -Wall -Wno-write-strings -Wextra -fno-rtti -s -static -static-libgcc -static-libstdc++ + +DEF_FILE += CatchCopy.def + +LIBS+= -lws2_32 -lole32 -luuid -static-libstdc++ -static-libgcc -static + +TEMPLATE = lib + +HEADERS += \ + Variable.h \ + Deque.h \ + resource.h \ + Reg.h \ + ClientCatchcopy.h \ + DDShellExt.h \ + ClassFactory.h + +SOURCES += \ + Deque.cpp \ + ClientCatchcopy.cpp \ + Reg.cpp \ + DDShellExt.cpp \ + ClassFactory.cpp \ + CatchCopy.cpp diff --git a/catchcopy-windows-explorer-plugin/ClassFactory.cpp b/catchcopy-windows-explorer-plugin/ClassFactory.cpp new file mode 100755 index 0000000..9ad7a5c --- /dev/null +++ b/catchcopy-windows-explorer-plugin/ClassFactory.cpp @@ -0,0 +1,84 @@ +
+#include "ClassFactory.h"
+#include "DDShellExt.h"
+#include <new>
+#include <Shlwapi.h>
+
+extern long g_cDllRef;
+
+ClassFactory::ClassFactory() : m_cRef(1)
+{
+ InterlockedIncrement(&g_cDllRef);
+}
+
+ClassFactory::~ClassFactory()
+{
+ InterlockedDecrement(&g_cDllRef);
+}
+
+// IUnknown
+HRESULT __stdcall ClassFactory::QueryInterface(const IID& iid, void **ppv)
+{
+ if(iid == IID_IUnknown || iid == IID_IClassFactory)
+ {
+ *ppv = static_cast<IClassFactory*>(this);
+ }
+ else
+ {
+ *ppv = NULL;
+ return E_NOINTERFACE;
+ }
+ reinterpret_cast<IUnknown*>(*ppv)->AddRef();
+ return S_OK;
+}
+ULONG __stdcall ClassFactory::AddRef()
+{
+ return InterlockedIncrement(&m_cRef);
+}
+
+ULONG __stdcall ClassFactory::Release()
+{
+ ULONG cRef = InterlockedDecrement(&m_cRef);
+ if (0 == cRef)
+ {
+ delete this;
+ }
+ return cRef;
+}
+
+//CreateInstance
+HRESULT __stdcall ClassFactory::CreateInstance(IUnknown *pIUnknownOuter, const IID& iid, void **ppv)
+{
+ HRESULT hr = CLASS_E_NOAGGREGATION;
+
+ // pIUnknownOuter is used for aggregation. We do not support it in the sample.
+ if (pIUnknownOuter == NULL)
+ {
+ hr = E_OUTOFMEMORY;
+
+ //// Create the COM component.
+ CDDShellExt *pExt = new (std::nothrow) CDDShellExt();
+ if (pExt)
+ {
+ // Query the specified interface.
+ hr = pExt->QueryInterface(iid, ppv);
+ pExt->Release();
+ }
+ }
+
+ return hr;
+}
+
+HRESULT __stdcall ClassFactory::LockServer(BOOL bLock)
+{
+ if(bLock == TRUE)
+ {
+ InterlockedIncrement(&g_cDllRef);
+ }
+ else
+ {
+ InterlockedDecrement(&g_cDllRef);
+ }
+ return S_OK;
+}
+
diff --git a/catchcopy-windows-explorer-plugin/ClassFactory.h b/catchcopy-windows-explorer-plugin/ClassFactory.h new file mode 100755 index 0000000..203ff40 --- /dev/null +++ b/catchcopy-windows-explorer-plugin/ClassFactory.h @@ -0,0 +1,22 @@ +#pragma once
+
+#include <unknwn.h> // For IClassFactory
+#include <windows.h>
+
+
+class ClassFactory : public IClassFactory
+{
+public:
+ //interface iunknown
+ virtual HRESULT __stdcall QueryInterface(const IID& iid, void **ppv);
+ virtual ULONG __stdcall AddRef();
+ virtual ULONG __stdcall Release();
+ //interface iclassfactory
+ virtual HRESULT __stdcall CreateInstance(IUnknown *pIUnknownOuter, const IID& iid, void **ppv);
+ virtual HRESULT __stdcall LockServer(BOOL bLock);
+
+ ClassFactory();
+ ~ClassFactory();
+private:
+ long m_cRef;
+};
diff --git a/catchcopy-windows-explorer-plugin/ClientCatchcopy.cpp b/catchcopy-windows-explorer-plugin/ClientCatchcopy.cpp new file mode 100755 index 0000000..2491795 --- /dev/null +++ b/catchcopy-windows-explorer-plugin/ClientCatchcopy.cpp @@ -0,0 +1,455 @@ +/** \file ClientCatchcopy.cpp
+\brief Define the catchcopy client
+\author alpha_one_x86
+\version 0002
+\date 2010 */
+
+#include <stdio.h>
+
+#include "ClientCatchcopy.h"
+#include <WinSock.h>
+//#pragma comment(lib, "Ws2_32.lib")
+
+#undef NONBLOCK_FLAG
+ClientCatchcopy::ClientCatchcopy()
+{
+ m_hpipe=NULL;
+ idNextOrder=0;
+ const char prefix[]="\\\\.\\pipe\\advanced-copier-";
+ char uname[1024];
+ DWORD len=1023;
+ char *data;
+ // false ??
+ if(GetUserNameA(uname, &len)!=FALSE)
+ {
+ // convert into hexa
+ data = toHex(uname);
+ m_pipename = (char *) malloc(sizeof(prefix)+strlen(data)+2);
+ #if defined(_MFC_VER)
+ strcpy_s(m_pipename, _countof(prefix) ,prefix);
+ strcat_s(m_pipename, sizeof(prefix)+strlen(data)+2,data);
+ #else
+ strcpy(m_pipename, prefix);
+ strcat(m_pipename, data);
+ #endif
+ free(data);
+ m_blk=NULL;
+ m_len=0;
+ m_tot=0;
+
+ canConnect=true;
+ }
+ else
+ {
+ #ifdef CATCHCOPY_EXPLORER_PLUGIN_DEBUG
+ void* lpBuffer;
+ FormatMessage( FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM,
+ NULL,
+ ::GetLastError(),
+ MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), // Default language
+ (LPTSTR) &lpBuffer,
+ 0,
+ NULL );
+ MessageBox(NULL,(LPCTSTR)lpBuffer, L"GetUserName Failed", MB_OK);
+ LocalFree( lpBuffer );
+ #endif // CATCHCOPY_EXPLORER_PLUGIN_DEBUG
+ canConnect=false;
+ }
+}
+
+ClientCatchcopy::~ClientCatchcopy()
+{
+ disconnectFromServer();
+}
+
+// Dump UTF16 (little endian)
+char * ClientCatchcopy::toHex(const char *str)
+{
+ char *p, *sz;
+ size_t len;
+ if (str==NULL)
+ return NULL;
+ len= strlen(str);
+ p = sz = (char *) malloc((len+1)*4);
+ // username goes hexa...
+ for (size_t i=0; i<len; i++)
+ {
+ #if defined(_MFC_VER)
+ sprintf_s(p, (len+1)*4, "%.2x00", str[i]);
+ #else
+ sprintf(p, "%.2x00", str[i]);
+ #endif
+ p+=4;
+ }
+ *p=0;
+ return sz;
+}
+
+bool ClientCatchcopy::connectToServer()
+{
+ if(!canConnect)
+ {
+ #ifdef CATCHCOPY_EXPLORER_PLUGIN_DEBUG
+ MessageBox(NULL,L"Can't connect due to previous error",L"Checking", MB_OK);
+ #endif // CATCHCOPY_EXPLORER_PLUGIN_DEBUG
+ return false;
+ }
+ if (m_hpipe==NULL)
+ {
+ #ifdef CATCHCOPY_EXPLORER_PLUGIN_DEBUG
+ char uname[1024];
+ DWORD len=1023;
+ GetUserNameA(uname, &len);
+ char temp_char_debug[1024];
+ sprintf(temp_char_debug, "user name: %s, pipe name: %s",uname , m_pipename);
+ MessageBoxA(NULL,temp_char_debug,"Pipe name", MB_OK);
+ #endif // CATCHCOPY_EXPLORER_PLUGIN_DEBUG
+ // create pipe
+ m_hpipe = CreateFileA(m_pipename, GENERIC_READ|GENERIC_WRITE|FILE_FLAG_OVERLAPPED , 0, NULL, OPEN_EXISTING, 0, NULL);
+ if (m_hpipe==INVALID_HANDLE_VALUE)
+ {
+ m_hpipe=NULL;
+ if (GetLastError()!= ERROR_PIPE_BUSY)
+ {
+ #ifdef CATCHCOPY_EXPLORER_PLUGIN_DEBUG
+ void* lpBuffer;
+ FormatMessage( FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM,
+ NULL,
+ ::GetLastError(),
+ MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), // Default language
+ (LPTSTR) &lpBuffer,
+ 0,
+ NULL );
+ MessageBox(NULL,(LPCTSTR)lpBuffer, L"Can't connect to catchcopy application compatible: GetLastError()!= ERROR_PIPE_BUSY", MB_OK);
+ LocalFree( lpBuffer );
+ #endif // CATCHCOPY_EXPLORER_PLUGIN_DEBUG
+ return false;
+ }
+ #ifdef NONBLOCK_FLAG
+ return false;
+ #else
+ if (!WaitNamedPipeA(m_pipename, 10000))
+ {
+ #ifdef CATCHCOPY_EXPLORER_PLUGIN_DEBUG
+ void* lpBuffer;
+ FormatMessage( FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM,
+ NULL,
+ ::GetLastError(),
+ MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), // Default language
+ (LPTSTR) &lpBuffer,
+ 0,
+ NULL );
+ MessageBox(NULL,(LPCTSTR)lpBuffer, L"Named pipe too long to responds", MB_OK);
+ LocalFree( lpBuffer );
+ #endif // CATCHCOPY_EXPLORER_PLUGIN_DEBUG
+ CloseHandle(m_hpipe);
+ m_hpipe=NULL;
+ return false;
+ }
+ #endif
+ }
+
+ #ifdef NONBLOCK_FLAG
+ // The pipe connected; change to pipe_nowait mode.
+ DWORD dwMode;
+ BOOL fSuccess = FALSE;
+ dwMode = PIPE_READMODE_BYTE|PIPE_NOWAIT;
+
+ fSuccess = SetNamedPipeHandleState(
+ m_hpipe, // pipe handle
+ &dwMode, // new pipe mode
+ NULL, // don't set maximum bytes
+ NULL); // don't set maximum time
+ if ( ! fSuccess)
+ {
+ #ifdef CATCHCOPY_EXPLORER_PLUGIN_DEBUG
+ char error_str[1024];
+ sprintf(error_str, "SetNamedPipeHandleState failed. GLE=%d\n", ::GetLastError() );
+ MessageBoxA( NULL, error_str,"SetNamedPipeHandleState error", MB_OK);
+ #endif // CATCHCOPY_EXPLORER_PLUGIN_DEBUG
+ return false;
+ }
+ #endif //NONBLOCK_FLAG
+ }
+ #ifdef CATCHCOPY_EXPLORER_PLUGIN_DEBUG
+ MessageBox(NULL,L"The explorer is now connected to the catchcopy compatible application",L"Checking", MB_OK);
+ #endif // CATCHCOPY_EXPLORER_PLUGIN_DEBUG
+
+ bool f = sendProtocol();
+ if(f!=true)
+ return false;
+ #if defined(_M_X64)
+ setClientName(L"Windows Explorer 64Bits");
+ #else
+ setClientName(L"Windows Explorer 32Bits");
+ #endif
+ return true;
+}
+
+void ClientCatchcopy::disconnectFromServer()
+{
+ clear();
+ if(m_hpipe!=NULL)
+ {
+ /* needed to not crash the server when have data to read */
+ FlushFileBuffers(m_hpipe);
+ CloseHandle(m_hpipe);
+ m_hpipe=NULL;
+ #ifdef CATCHCOPY_EXPLORER_PLUGIN_DEBUG
+ MessageBox(NULL, L"The explorer is now disconnected of the catchcopy compatible application",L"Checking", MB_OK);
+ #endif // CATCHCOPY_EXPLORER_PLUGIN_DEBUG
+ }
+}
+
+/// \brief to send order
+bool ClientCatchcopy::sendProtocol()
+{
+ CDeque data;
+ data.push_back(L"protocol");
+ data.push_back(L"0002");
+ return sendRawOrderList(data);
+}
+
+bool ClientCatchcopy::setClientName(wchar_t *name)
+{
+ CDeque data;
+ data.push_back(L"client");
+ data.push_back(name);
+ return sendRawOrderList(data);
+}
+
+bool ClientCatchcopy::addCopyWithDestination(CDeque sources,wchar_t *destination)
+{
+ sources.push_front(L"cp");
+ sources.push_back(destination);
+ #ifdef CATCHCOPY_EXPLORER_PLUGIN_DEBUG
+ MessageBox(NULL, "sources size: "+sources.size()+", first: "+sources.at(0),L"Checking", MB_OK);
+ #endif // CATCHCOPY_EXPLORER_PLUGIN_DEBUG
+ return sendRawOrderList(sources);
+}
+
+bool ClientCatchcopy::addCopyWithoutDestination(CDeque sources)
+{
+ sources.push_front(L"cp-?");
+ #ifdef CATCHCOPY_EXPLORER_PLUGIN_DEBUG
+ MessageBox(NULL, "sources size: "+sources.size()+", first: "+sources.at(0),L"Checking", MB_OK);
+ #endif // CATCHCOPY_EXPLORER_PLUGIN_DEBUG
+ return sendRawOrderList(sources);
+}
+
+bool ClientCatchcopy::addMoveWithDestination(CDeque sources, wchar_t *destination)
+{
+ sources.push_front(L"mv");
+ sources.push_back(destination);
+ #ifdef CATCHCOPY_EXPLORER_PLUGIN_DEBUG
+ MessageBox(NULL, "sources size: "+sources.size()+", first: "+sources.at(0),L"Checking", MB_OK);
+ #endif // CATCHCOPY_EXPLORER_PLUGIN_DEBUG
+ return sendRawOrderList(sources);
+}
+
+bool ClientCatchcopy::addMoveWithoutDestination(CDeque sources)
+{
+ sources.push_front(L"mv-?");
+ #ifdef CATCHCOPY_EXPLORER_PLUGIN_DEBUG
+ MessageBox(NULL, "sources size: "+sources.size()+", first: "+sources.at(0),L"Checking", MB_OK);
+ #endif // CATCHCOPY_EXPLORER_PLUGIN_DEBUG
+ return sendRawOrderList(sources);
+}
+
+/// \brief to send stream of string list
+bool ClientCatchcopy::sendRawOrderList(CDeque order, bool first_try)
+{
+ if(m_hpipe!=NULL)
+ {
+ int data_size=sizeof(int)*3;
+ for(int i=0;i<order.size();i++)
+ {
+ if (order.at(i) == NULL)
+ continue;
+
+ data_size+=(int)sizeof(int);
+ data_size+=(int)sizeof(wchar_t)*(int)wcslen(order.at(i));
+ }
+ addInt32(data_size);
+ addInt32(idNextOrder++);
+ addInt32((int)order.size());
+ for(int i=0;i<order.size();i++)
+ {
+ if (order.at(i) == NULL)
+ continue;
+
+ //set string contenant
+ addStr(order.at(i));
+ }
+ if(dataToPipe()<0)
+ {
+ if(first_try)
+ {
+ disconnectFromServer();
+ connectToServer();
+ return sendRawOrderList(order,false);
+ }
+ else
+ clear();
+ }
+ return true;
+ }
+ else
+ {
+ clear();
+ return false;
+ }
+}
+
+// Send data block to named pipe
+int ClientCatchcopy::dataToPipe()
+{
+ byte_t *ptr;
+ int ret=0, max;
+ if (m_hpipe!=NULL)
+ {
+ ptr = m_blk;
+ while (!ret && m_len)
+ {
+ max=(m_len>BUFFER_PIPE) ? BUFFER_PIPE:m_len;
+ #ifdef NONBLOCK_FLAG
+ writePipe_nonBlock(m_hpipe, ptr, max);
+ break;
+ #else
+ if(writePipe(m_hpipe, ptr, max)!=0)
+ {
+ ret=-2;
+ break;
+ }
+ m_len-=max;
+ ptr+=max;
+ #endif
+ }
+ }
+ return ret;
+}
+
+int ClientCatchcopy::writePipe(HANDLE hPipe, byte_t *ptr, int len)
+{
+ DWORD cbWritten;
+ if (!WriteFile(hPipe, ptr, len, &cbWritten, NULL))
+ return -4;
+ return 0;
+}
+
+#ifdef NONBLOCK_FLAG
+int ClientCatchcopy::writePipe_nonBlock(HANDLE hPipe, byte_t *ptr, int len)
+{
+ DWORD cbWritten;
+ WriteFile(hPipe, ptr, len, &cbWritten, NULL);
+ return 0;
+}
+#endif
+
+// Add int32 (big-endian) into binary block
+int ClientCatchcopy::addInt32(int value)
+{
+ blkGrowing(sizeof(int));
+ // add value
+ setInt32(m_len, value);
+ m_len+=sizeof(int);
+ return m_len-sizeof(int);
+}
+
+void ClientCatchcopy::setInt32(int offset, int value)
+{
+ C_INT(m_blk+offset)=htonl(value);
+}
+
+// Add unicode string into binary block from ASCIIZ
+int ClientCatchcopy::addStr(WCHAR *data)
+{
+ int ret=-1, len;
+ WCHAR *x;
+ if (data!=NULL && *data)
+ {
+ // le => be
+ x = _wcsdup(data);
+ len = toBigEndian(x);
+ // set size of string
+ ret = addInt32(len);
+ // and add it to block
+ blkGrowing(len);
+ memmove(m_blk+m_len, x, len);
+ m_len+=len;
+ free(x);
+ }
+ return ret;
+}
+
+// resize binary block (if needed)
+byte_t *ClientCatchcopy::blkGrowing(int added)
+{
+ if (m_len+added>m_tot)
+ {
+ // check if added isn't bigger than buffer itself...
+ m_tot+= (added>BLOCK_SIZ) ? added:BLOCK_SIZ;
+ m_blk = (byte_t *) realloc(m_blk, m_tot);
+ }
+ return m_blk+m_len;
+}
+
+int ClientCatchcopy::toBigEndian(WCHAR *p)
+{
+ WCHAR tmp;
+ int ret=0;
+ while(*p)
+ {
+ tmp = htons(*p);
+ *p++=tmp;
+ ret+=2;
+ }
+ return ret;
+}
+
+void ClientCatchcopy::clear()
+{
+ m_tot=0;
+ m_len=0;
+ idNextOrder=0;
+ if (m_blk!=NULL)
+ {
+ free(m_blk);
+ m_blk=NULL;
+ }
+}
+
+bool ClientCatchcopy::isConnected()
+{
+ if(m_hpipe==NULL)
+ return false;
+
+ bool fSuccess = PeekNamedPipe(
+ m_hpipe,
+ NULL,
+ 0,
+ 0,
+ 0,
+ 0
+ );
+
+ if(!fSuccess && GetLastError() != ERROR_MORE_DATA)
+ {
+ #ifdef CATCHCOPY_EXPLORER_PLUGIN_DEBUG
+ void* lpBuffer;
+ FormatMessage( FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM,
+ NULL,
+ ::GetLastError(),
+ MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), // Default language
+ (LPTSTR) &lpBuffer,
+ 0,
+ NULL );
+ MessageBox(NULL,(LPCTSTR)lpBuffer, L"Error detected with the connexion", MB_OK);
+ LocalFree( lpBuffer );
+ #endif // CATCHCOPY_EXPLORER_PLUGIN_DEBUG
+ disconnectFromServer();
+ return false;
+ }
+ else
+ return true;
+}
diff --git a/catchcopy-windows-explorer-plugin/ClientCatchcopy.h b/catchcopy-windows-explorer-plugin/ClientCatchcopy.h new file mode 100755 index 0000000..954bff7 --- /dev/null +++ b/catchcopy-windows-explorer-plugin/ClientCatchcopy.h @@ -0,0 +1,68 @@ +/** \file ClientCatchcopy.h +\brief Define the catchcopy client +\author alpha_one_x86 +\version 0002 +\date 2010 */ + +#ifndef CLIENTCATCHCOPY_H +#define CLIENTCATCHCOPY_H + +#define NONBLOCK_FLAG +#define BUFSIZE 512 +#define S_LEN 8 + +#define C_INT(p) *((int *) (p)) +#define BLOCK_SIZ 64000 +#define BUFFER_PIPE 32000 + +#include <windows.h> +#include <string> +#include <deque> +#include <stdlib.h> + +#include "Variable.h" +#include "Deque.h" + +typedef unsigned char byte_t; + +class ClientCatchcopy +{ + public: + ClientCatchcopy(); + ~ClientCatchcopy(); + bool connectToServer(); + void disconnectFromServer(); + /// \brief to send order + bool sendProtocol(); + bool setClientName(wchar_t *name); + bool addCopyWithDestination(CDeque sources,wchar_t *destination); + bool addCopyWithoutDestination(CDeque sources); + bool addMoveWithDestination(CDeque sources,wchar_t *destination); + bool addMoveWithoutDestination(CDeque sources); + /// \brief to send stream of string list + bool sendRawOrderList(CDeque order,bool first_try=true); + bool isConnected(); + private: + HANDLE m_hpipe; + unsigned int idNextOrder; + char *m_pipename; + byte_t *m_blk; + int m_tot; + int m_len; + + char * toHex(const char *str); + int dataToPipe(); + int addInt32(int value); + int addStr(WCHAR *data); + byte_t *blkGrowing(int added); + void setInt32(int offset, int value); + int toBigEndian(WCHAR *p); + void clear(); + int writePipe(HANDLE hPipe, byte_t *ptr, int len); + #ifdef NONBLOCK_FLAG + int writePipe_nonBlock(HANDLE hPipe, byte_t *ptr, int len); + #endif + bool canConnect; +}; + +#endif // CLIENTCATCHCOPY_H diff --git a/catchcopy-windows-explorer-plugin/DDShellExt.cpp b/catchcopy-windows-explorer-plugin/DDShellExt.cpp new file mode 100755 index 0000000..25142d5 --- /dev/null +++ b/catchcopy-windows-explorer-plugin/DDShellExt.cpp @@ -0,0 +1,188 @@ +// DDShellExt.cpp : Implementation of CDDShellExt
+
+#include "tchar.h"
+#include "DDShellExt.h"
+#include "ClientCatchcopy.h"
+
+#include <Shlwapi.h>
+
+extern HINSTANCE g_hInst;
+extern long g_cDllRef;
+
+CDDShellExt::CDDShellExt(): m_cRef(1)
+{
+ InterlockedIncrement(&g_cDllRef);
+}
+
+CDDShellExt::~CDDShellExt()
+{
+ InterlockedDecrement(&g_cDllRef);
+}
+
+// Query to the interface the component supported.
+IFACEMETHODIMP CDDShellExt::QueryInterface(REFIID riid, void **ppv)
+{
+ if(riid == IID_IUnknown || riid == IID_IContextMenu)
+ {
+ *ppv = static_cast<IContextMenu*>(this);
+ }
+ else if (riid == IID_IShellExtInit)
+ {
+ *ppv = static_cast<IShellExtInit*>(this);
+ }
+ else
+ {
+ *ppv = NULL;
+ return E_NOINTERFACE;
+ }
+ reinterpret_cast<IUnknown*>(*ppv)->AddRef();
+ return S_OK;
+}
+
+// Increase the reference count for an interface on an object.
+IFACEMETHODIMP_(ULONG) CDDShellExt::AddRef()
+{
+ return InterlockedIncrement(&m_cRef);
+}
+
+// Decrease the reference count for an interface on an object.
+IFACEMETHODIMP_(ULONG) CDDShellExt::Release()
+{
+ ULONG cRef = InterlockedDecrement(&m_cRef);
+ if (0 == cRef)
+ delete this;
+ return cRef;
+}
+
+STDMETHODIMP CDDShellExt::Initialize(LPCITEMIDLIST pidlFolder,LPDATAOBJECT pDO,HKEY hProgID)
+{
+ (void)hProgID;
+ if(!connected)
+ {
+ bool b = m_ac.connectToServer();
+
+ if (b==true)
+ {
+ connected=true;
+ }
+ else
+ return E_FAIL;
+ }
+
+ FORMATETC fmt={CF_HDROP,NULL,DVASPECT_CONTENT,-1,TYMED_HGLOBAL};
+ STGMEDIUM stg={TYMED_HGLOBAL};
+ HDROP hDrop;
+
+ fDestDir[0]=0;
+ if (!SHGetPathFromIDList(pidlFolder,fDestDir))
+ {
+ #ifdef CATCHCOPY_EXPLORER_PLUGIN_DEBUG
+ MessageBox(NULL,L"Initialize",L"E_FAIL 1",MB_OK);
+ #endif // CATCHCOPY_EXPLORER_PLUGIN_DEBUG
+ return E_FAIL;
+ }
+
+ // Detect if it's explorer that started the operation by enumerating available
+ // clipboard formats and searching for one that only explorer uses
+ IEnumFORMATETC *en;
+ FORMATETC fmt2;
+ WCHAR fmtName[65535]=L"\0";
+ fFromExplorer=false;
+ pDO->EnumFormatEtc(DATADIR_GET,&en);
+ while(en->Next(1,&fmt2,NULL)==S_OK){
+ GetClipboardFormatName(fmt2.cfFormat,fmtName,sizeof(fmtName));
+ if (!wcscmp(fmtName,CFSTR_SHELLIDLIST)) fFromExplorer=true;
+ }
+ en->Release();
+
+ // Look for CF_HDROP data in the data object. If there
+ // is no such data, return an error back to Explorer.
+ if (FAILED(pDO->GetData(&fmt,&stg)))
+ {
+ #ifdef CATCHCOPY_EXPLORER_PLUGIN_DEBUG
+ MessageBox(NULL,L"Initialize",L"E_INVALIDARG 2",MB_OK);
+ #endif // CATCHCOPY_EXPLORER_PLUGIN_DEBUG
+ return E_INVALIDARG;
+ }
+
+ // Get a pointer to the actual data.
+ hDrop=(HDROP)GlobalLock(stg.hGlobal);
+
+ // Make sure it worked.
+ if (hDrop==NULL)
+ {
+ #ifdef CATCHCOPY_EXPLORER_PLUGIN_DEBUG
+ MessageBox(NULL,L"Initialize",L"E_INVALIDARG 1",MB_OK);
+ #endif // CATCHCOPY_EXPLORER_PLUGIN_DEBUG
+ return E_INVALIDARG;
+ }
+
+ UINT numFiles,i;
+ WCHAR fn[MAX_PATH]=L"";
+
+ numFiles=DragQueryFile(hDrop,0xFFFFFFFF,NULL,0);
+
+ if (numFiles)
+ {
+ for(i=0;i<numFiles;++i)
+ {
+ if(DragQueryFile(hDrop,i,fn,MAX_PATH))
+ sources.push_back(fn);
+ }
+ }
+
+ GlobalUnlock(stg.hGlobal);
+ ReleaseStgMedium(&stg);
+
+ return S_OK;
+}
+
+STDMETHODIMP CDDShellExt::QueryContextMenu(HMENU hmenu,UINT uMenuIndex,UINT uidFirstCmd,UINT uidLastCmd,UINT uFlags)
+{
+ (void)uidLastCmd;
+ if(!m_ac.isConnected())
+ {
+ if(!m_ac.connectToServer())
+ return E_FAIL;
+ }
+ if (uFlags&CMF_DEFAULTONLY)
+ return MAKE_HRESULT(SEVERITY_SUCCESS,FACILITY_NULL,0);
+
+ int x=uidFirstCmd;
+
+ InsertMenu(hmenu,uMenuIndex++,MF_STRING|MF_BYPOSITION,x++,L"Copy with advanced software");
+ InsertMenu(hmenu,uMenuIndex++,MF_STRING|MF_BYPOSITION,x++,L"Move with advanced software");
+
+ int defItem=GetMenuDefaultItem(hmenu,false,0);
+ if (defItem==1) // 1: Copy
+ {
+ if (fFromExplorer)
+ SetMenuDefaultItem(hmenu,uidFirstCmd,false);
+ }
+ else if (defItem==2) //2: Move
+ {
+ SetMenuDefaultItem(hmenu,uidFirstCmd+1,false);
+ }
+ return MAKE_HRESULT(SEVERITY_SUCCESS,FACILITY_NULL,2);
+}
+
+
+STDMETHODIMP CDDShellExt::InvokeCommand ( LPCMINVOKECOMMANDINFO pInfo )
+{
+ if(HIWORD(pInfo->lpVerb))
+ return E_INVALIDARG;
+ switch(LOWORD(pInfo->lpVerb))
+ {
+ case 0:// copy
+ if(!m_ac.addCopyWithDestination(sources,fDestDir))
+ return E_FAIL;
+ break;
+ case 1:// move
+ if(!m_ac.addMoveWithDestination(sources,fDestDir))
+ return E_FAIL;
+ break;
+ default :
+ return S_OK;
+ }
+ return S_OK;
+}
diff --git a/catchcopy-windows-explorer-plugin/DDShellExt.h b/catchcopy-windows-explorer-plugin/DDShellExt.h new file mode 100755 index 0000000..9e9f68f --- /dev/null +++ b/catchcopy-windows-explorer-plugin/DDShellExt.h @@ -0,0 +1,46 @@ +// DDShellExt.h : Declaration of the CDDShellExt
+
+#pragma once
+#include "resource.h" // main symbols
+#include "shlobj.h"
+#include "ClientCatchcopy.h"
+#include "Variable.h"
+#include "Deque.h"
+
+static bool connected=false;
+static ClientCatchcopy m_ac;
+
+// CDDShellExt
+
+extern const CLSID CLSID_DDShellExt;
+
+class CDDShellExt :
+ public IShellExtInit,
+ public IContextMenu
+{
+private:
+ static int fBaselistHandle;
+ bool fFromExplorer;
+ WCHAR fDestDir[MAX_PATH];
+ //static ClientCatchcopy m_ac;
+ CDeque sources;
+ //static bool connected;
+
+ // Reference count of component.
+ long m_cRef;
+public:
+ // IUnknown
+ IFACEMETHODIMP QueryInterface(REFIID riid, void **ppv);
+ IFACEMETHODIMP_(ULONG) AddRef();
+ IFACEMETHODIMP_(ULONG) Release();
+
+ // IShellExtInit
+ STDMETHODIMP Initialize(LPCITEMIDLIST, LPDATAOBJECT, HKEY);
+
+ CDDShellExt(void);
+ ~CDDShellExt(void);
+ // IContextMenu
+ STDMETHODIMP GetCommandString(UINT_PTR idCmd,UINT uFlags,UINT* pwReserved,LPSTR pszName,UINT cchMax){(void)idCmd;(void)uFlags;(void)pwReserved;(void)pszName;(void)cchMax;(void)connected;return E_NOTIMPL;};
+ STDMETHODIMP InvokeCommand(LPCMINVOKECOMMANDINFO);
+ STDMETHODIMP QueryContextMenu(HMENU,UINT,UINT,UINT,UINT);
+};
diff --git a/catchcopy-windows-explorer-plugin/Deque.cpp b/catchcopy-windows-explorer-plugin/Deque.cpp new file mode 100755 index 0000000..93a9fcb --- /dev/null +++ b/catchcopy-windows-explorer-plugin/Deque.cpp @@ -0,0 +1,100 @@ +#include "Deque.h"
+#include <windows.h>
+
+CDeque::CDeque(void)
+{
+ top1=0;
+ top2=0;
+ head=NULL;
+ tail=NULL;
+}
+
+CDeque::~CDeque(void)
+{
+}
+
+void CDeque::push_front(wchar_t *str)
+{
+ CNode *temp;
+ if(top1+top2 >= MAX_DEQUE)
+ {
+ return ;
+ }
+
+ if(top1+top2 == 0)
+ {
+ head = new CNode;
+ wcscpy(head->str, str);
+ head->next=NULL;
+ head->prev=NULL;
+ tail=head;
+ top1++;
+ }
+ else
+ {
+ top1++;
+ temp=new CNode;
+ wcscpy(temp->str, str);
+ temp->next=head;
+ temp->prev=NULL;
+ head->prev=temp;
+ head=temp;
+ }
+}
+
+void CDeque::push_back(wchar_t *str)
+{
+ CNode *temp;
+ if(top1+top2 >= MAX_DEQUE)
+ {
+ return ;
+ }
+ if(top1+top2 == 0)
+ {
+ head = new CNode;
+ wcscpy(head->str, str);
+ head->next=NULL;
+ head->prev=NULL;
+ tail=head;
+ top1++;
+ }
+ else
+ {
+ top2++;
+ temp=new CNode;
+ wcscpy(temp->str, str);
+ temp->next=NULL;
+ temp->prev=tail;
+ tail->next=temp;
+ tail=temp;
+ }
+}
+
+int CDeque::size()
+{
+ return top1 + top2;
+}
+
+wchar_t *CDeque::at(int pos)
+{
+ int i=0;
+ CNode *temp;
+
+ if(top1+top2 <= 0)
+ {
+ return NULL;
+ }
+
+ temp=head;
+ while(temp!=NULL)
+ {
+ if(i==pos)
+ return temp->str;
+
+ temp=temp->next;
+
+ i++;
+ }
+
+ return NULL;
+}
diff --git a/catchcopy-windows-explorer-plugin/Deque.h b/catchcopy-windows-explorer-plugin/Deque.h new file mode 100755 index 0000000..e0e1f28 --- /dev/null +++ b/catchcopy-windows-explorer-plugin/Deque.h @@ -0,0 +1,29 @@ +#pragma once
+
+#define MAX_STR_LEN 512
+#define MAX_DEQUE 512
+
+class CNode
+{
+public:
+ wchar_t str[MAX_STR_LEN];
+ class CNode *next;
+ class CNode *prev;
+};
+
+class CDeque : public CNode
+{
+public:
+ CDeque(void);
+ ~CDeque(void);
+
+private:
+ CNode *head,*tail;
+ int top1,top2;
+
+public:
+ void push_front(wchar_t *str);
+ void push_back(wchar_t *str);
+ int size();
+ wchar_t *at(int pos);
+};
diff --git a/catchcopy-windows-explorer-plugin/Reg.cpp b/catchcopy-windows-explorer-plugin/Reg.cpp new file mode 100755 index 0000000..37f7cc1 --- /dev/null +++ b/catchcopy-windows-explorer-plugin/Reg.cpp @@ -0,0 +1,403 @@ +#include "Reg.h"
+#include <strsafe.h>
+
+//
+// FUNCTION: SetHKCRRegistryKeyAndValue
+//
+// PURPOSE: The function creates a HKCR registry key and sets the specified
+// registry value.
+//
+// PARAMETERS:
+// * pszSubKey - specifies the registry key under HKCR. If the key does not
+// exist, the function will create the registry key.
+// * pszValueName - specifies the registry value to be set. If pszValueName
+// is NULL, the function will set the default value.
+// * pszData - specifies the string data of the registry value.
+//
+// RETURN VALUE:
+// If the function succeeds, it returns S_OK. Otherwise, it returns an
+// HRESULT error code.
+//
+HRESULT SetHKCRRegistryKeyAndValue(PCWSTR pszSubKey, PCWSTR pszValueName,
+ PCWSTR pszData)
+{
+ HRESULT hr;
+ HKEY hKey = NULL;
+
+ // Creates the specified registry key. If the key already exists, the
+ // function opens it.
+ hr = HRESULT_FROM_WIN32(RegCreateKeyEx(
+ #ifdef CATCHCOPY_ROOT_MODE
+ HKEY_CLASSES_ROOT
+ #else
+ HKEY_CURRENT_USER
+ #endif
+ , pszSubKey, 0,
+ NULL, REG_OPTION_NON_VOLATILE, KEY_ALL_ACCESS | KEY_WOW64_64KEY, NULL, &hKey, NULL));
+
+ if (SUCCEEDED(hr))
+ {
+ if (pszData != NULL)
+ {
+ // Set the specified value of the key.
+ DWORD cbData = lstrlen(pszData) * sizeof(*pszData);
+ hr = HRESULT_FROM_WIN32(RegSetValueEx(hKey, pszValueName, 0,
+ REG_SZ, reinterpret_cast<const BYTE *>(pszData), cbData));
+ }
+
+ RegCloseKey(hKey);
+ }
+
+ return hr;
+}
+
+LONG RecursiveDeleteKey(HKEY hKeyParent, PCWSTR szKeyChild)
+{
+ // Open the child.
+ HKEY hKeyChild ;
+ LONG lRes = RegOpenKeyEx(hKeyParent, szKeyChild, 0,
+ KEY_ALL_ACCESS | KEY_WOW64_64KEY, &hKeyChild) ;
+ if (lRes != ERROR_SUCCESS)
+ {
+ return lRes ;
+ }
+ // Enumerate all of the decendents of this child.
+ FILETIME time ;
+ wchar_t szBuffer[MAX_PATH];
+ DWORD dwSize = MAX_PATH ;
+ while (RegEnumKeyEx(hKeyChild, 0, (LPWSTR)szBuffer, &dwSize, NULL,
+ NULL, NULL, &time) == ERROR_SUCCESS)
+ {
+ // Delete the decendents of this child.
+ lRes = RecursiveDeleteKey(hKeyChild, (PCWSTR)szBuffer) ;
+ if (lRes != ERROR_SUCCESS)
+ {
+ // Cleanup before exiting.
+ RegCloseKey(hKeyChild) ;
+ return lRes;
+ }
+ dwSize = MAX_PATH ;
+ }
+
+ // Close the child.
+ RegCloseKey(hKeyChild) ;
+
+ // Delete this child.
+ return RegDeleteKey(hKeyParent, szKeyChild) ;
+}
+
+//
+// FUNCTION: GetHKCRRegistryKeyAndValue
+//
+// PURPOSE: The function opens a HKCR registry key and gets the data for the
+// specified registry value name.
+//
+// PARAMETERS:
+// * pszSubKey - specifies the registry key under HKCR. If the key does not
+// exist, the function returns an error.
+// * pszValueName - specifies the registry value to be retrieved. If
+// pszValueName is NULL, the function will get the default value.
+// * pszData - a pointer to a buffer that receives the value's string data.
+// * cbData - specifies the size of the buffer in bytes.
+//
+// RETURN VALUE:
+// If the function succeeds, it returns S_OK. Otherwise, it returns an
+// HRESULT error code. For example, if the specified registry key does not
+// exist or the data for the specified value name was not set, the function
+// returns COR_E_FILENOTFOUND (0x80070002).
+//
+HRESULT GetHKCRRegistryKeyAndValue(PCWSTR pszSubKey, PCWSTR pszValueName,
+ PWSTR pszData, DWORD cbData)
+{
+ HRESULT hr;
+ HKEY hKey = NULL;
+
+ // Try to open the specified registry key.
+ hr = HRESULT_FROM_WIN32(RegOpenKeyEx(
+ #ifdef CATCHCOPY_ROOT_MODE
+ HKEY_CLASSES_ROOT
+ #else
+ HKEY_CURRENT_USER
+ #endif
+ , pszSubKey, 0,
+ KEY_READ, &hKey));
+
+ if (SUCCEEDED(hr))
+ {
+ // Get the data for the specified value name.
+ hr = HRESULT_FROM_WIN32(RegQueryValueEx(hKey, pszValueName, NULL,
+ NULL, reinterpret_cast<LPBYTE>(pszData), &cbData));
+
+ RegCloseKey(hKey);
+ }
+
+ return hr;
+}
+
+//
+// FUNCTION: RegisterInprocServer
+//
+// PURPOSE: Register the in-process component in the registry.
+//
+// PARAMETERS:
+// * pszModule - Path of the module that contains the component
+// * clsid - Class ID of the component
+// * pszFriendlyName - Friendly name
+// * pszThreadModel - Threading model
+//
+// NOTE: The function creates the HKCR\CLSID\{<CLSID>} key in the registry.
+//
+// HKCR
+// {
+// NoRemove CLSID
+// {
+// ForceRemove {<CLSID>} = s '<Friendly Name>'
+// {
+// InprocServer32 = s '%MODULE%'
+// {
+// val ThreadingModel = s '<Thread Model>'
+// }
+// }
+// }
+// }
+//
+HRESULT RegisterInprocServer(PCWSTR pszModule, const CLSID& clsid, PCWSTR pszFriendlyName, PCWSTR pszThreadModel)
+{
+ if (pszModule == NULL || pszThreadModel == NULL)
+ {
+ return E_INVALIDARG;
+ }
+
+ HRESULT hr;
+
+ wchar_t szCLSID[MAX_PATH];
+ StringFromGUID2(clsid, szCLSID, ARRAYSIZE(szCLSID));
+
+ wchar_t szSubkey[MAX_PATH];
+
+ // Create the HKCR\CLSID\{<CLSID>} key.
+ hr = StringCchPrintf(szSubkey, ARRAYSIZE(szSubkey),
+ #ifdef CATCHCOPY_ROOT_MODE
+ L"CLSID\\%s"
+ #else
+ L"Software\\Classes\\CLSID\\%s"
+ #endif
+ , szCLSID);
+ if (SUCCEEDED(hr))
+ {
+ hr = SetHKCRRegistryKeyAndValue(szSubkey, NULL, pszFriendlyName);
+
+ // Create the HKCR\CLSID\{<CLSID>}\InprocServer32 key.
+ if (SUCCEEDED(hr))
+ {
+ hr = StringCchPrintf(szSubkey, ARRAYSIZE(szSubkey),
+ #ifdef CATCHCOPY_ROOT_MODE
+ L"CLSID\\%s\\InprocServer32"
+ #else
+ L"Software\\Classes\\CLSID\\%s\\InprocServer32"
+ #endif
+ , szCLSID);
+ if (SUCCEEDED(hr))
+ {
+ // Set the default value of the InprocServer32 key to the
+ // path of the COM module.
+ hr = SetHKCRRegistryKeyAndValue(szSubkey, NULL, pszModule);
+ if (SUCCEEDED(hr))
+ {
+ // Set the threading model of the component.
+ hr = SetHKCRRegistryKeyAndValue(szSubkey, L"ThreadingModel", pszThreadModel);
+ }
+ }
+ }
+ }
+
+ return hr;
+}
+
+
+//
+// FUNCTION: UnregisterInprocServer
+//
+// PURPOSE: Unegister the in-process component in the registry.
+//
+// PARAMETERS:
+// * clsid - Class ID of the component
+//
+// NOTE: The function deletes the HKCR\CLSID\{<CLSID>} key in the registry.
+//
+HRESULT UnregisterInprocServer(const CLSID& clsid)
+{
+ HRESULT hr = S_OK;
+
+ wchar_t szCLSID[MAX_PATH];
+ StringFromGUID2(clsid, szCLSID, ARRAYSIZE(szCLSID));
+
+ wchar_t szSubkey[MAX_PATH];
+
+ // Delete the HKCR\CLSID\{<CLSID>} key.
+ hr = StringCchPrintf(szSubkey, ARRAYSIZE(szSubkey),
+ #ifdef CATCHCOPY_ROOT_MODE
+ L"CLSID\\%s"
+ #else
+ L"Software\\Classes\\CLSID\\%s"
+ #endif
+ , szCLSID);
+
+ if (SUCCEEDED(hr))
+ {
+ hr = HRESULT_FROM_WIN32(RecursiveDeleteKey(
+ #ifdef CATCHCOPY_ROOT_MODE
+ HKEY_CLASSES_ROOT
+ #else
+ HKEY_CURRENT_USER
+ #endif
+ , szSubkey));
+ }
+
+ return hr;
+}
+//
+// FUNCTION: RegisterShellExtContextMenuHandler
+//
+// PURPOSE: Register the context menu handler.
+//
+// PARAMETERS:
+// * pszFileType - The file type that the context menu handler is
+// associated with. For example, '*' means all file types; '.txt' means
+// all .txt files. The parameter must not be NULL.
+// * clsid - Class ID of the component
+// * pszFriendlyName - Friendly name
+//
+// NOTE: The function creates the following key in the registry.
+//
+// HKCR
+// {
+// NoRemove <File Type>
+// {
+// NoRemove shellex
+// {
+// NoRemove ContextMenuHandlers
+// {
+// {<CLSID>} = s '<Friendly Name>'
+// }
+// }
+// }
+// }
+//
+HRESULT RegisterShellExtContextMenuHandler(
+ PCWSTR pszFileType, const CLSID& clsid, PCWSTR pszFriendlyName)
+{
+ if (pszFileType == NULL)
+ {
+ return E_INVALIDARG;
+ }
+
+ HRESULT hr;
+
+ wchar_t szCLSID[MAX_PATH];
+ StringFromGUID2(clsid, szCLSID, ARRAYSIZE(szCLSID));
+
+ wchar_t szSubkey[MAX_PATH];
+
+ // If pszFileType starts with '.', try to read the default value of the
+ // HKCR\<File Type> key which contains the ProgID to which the file type
+ // is linked.
+ if (*pszFileType == L'.')
+ {
+ wchar_t szDefaultVal[260];
+ hr = GetHKCRRegistryKeyAndValue(pszFileType, NULL, szDefaultVal,
+ sizeof(szDefaultVal));
+
+ // If the key exists and its default value is not empty, use the
+ // ProgID as the file type.
+ if (SUCCEEDED(hr) && szDefaultVal[0] != L'\0')
+ {
+ pszFileType = szDefaultVal;
+ }
+ }
+
+ // Create the key HKCR\<File Type>\shellex\DragDropHandlers\{<CLSID>}
+ hr = StringCchPrintf(szSubkey, ARRAYSIZE(szSubkey),
+ #ifdef CATCHCOPY_ROOT_MODE
+ L"%s\\shellex\\DragDropHandlers\\%s"
+ #else
+ L"Software\\Classes\\%s\\shellex\\DragDropHandlers\\%s"
+ #endif
+ , pszFileType, szCLSID);
+ if (SUCCEEDED(hr))
+ {
+ // Set the default value of the key.
+ hr = SetHKCRRegistryKeyAndValue(szSubkey, NULL, pszFriendlyName);
+ }
+
+ return hr;
+}
+
+
+//
+// FUNCTION: UnregisterShellExtContextMenuHandler
+//
+// PURPOSE: Unregister the context menu handler.
+//
+// PARAMETERS:
+// * pszFileType - The file type that the context menu handler is
+// associated with. For example, '*' means all file types; '.txt' means
+// all .txt files. The parameter must not be NULL.
+// * clsid - Class ID of the component
+//
+// NOTE: The function removes the {<CLSID>} key under
+// HKCR\<File Type>\shellex\ContextMenuHandlers in the registry.
+//
+HRESULT UnregisterShellExtContextMenuHandler(
+ PCWSTR pszFileType, const CLSID& clsid)
+{
+ if (pszFileType == NULL)
+ {
+ return E_INVALIDARG;
+ }
+
+ HRESULT hr;
+
+ wchar_t szCLSID[MAX_PATH];
+ StringFromGUID2(clsid, szCLSID, ARRAYSIZE(szCLSID));
+
+ wchar_t szSubkey[MAX_PATH];
+
+ // If pszFileType starts with '.', try to read the default value of the
+ // HKCR\<File Type> key which contains the ProgID to which the file type
+ // is linked.
+ if (*pszFileType == L'.')
+ {
+ wchar_t szDefaultVal[260];
+ hr = GetHKCRRegistryKeyAndValue(pszFileType, NULL, szDefaultVal,
+ sizeof(szDefaultVal));
+
+ // If the key exists and its default value is not empty, use the
+ // ProgID as the file type.
+ if (SUCCEEDED(hr) && szDefaultVal[0] != L'\0')
+ {
+ pszFileType = szDefaultVal;
+ }
+ }
+
+ // Remove the HKCR\<File Type>\shellex\DragDropHandlers\{<CLSID>} key.
+ hr = StringCchPrintf(szSubkey, ARRAYSIZE(szSubkey),
+ #ifdef CATCHCOPY_ROOT_MODE
+ L"%s\\shellex\\DragDropHandlers\\%s"
+ #else
+ L"Software\\Classes\\%s\\shellex\\DragDropHandlers\\%s"
+ #endif
+ , pszFileType, szCLSID);
+ if (SUCCEEDED(hr))
+ {
+ hr = HRESULT_FROM_WIN32(RecursiveDeleteKey(
+ #ifdef CATCHCOPY_ROOT_MODE
+ HKEY_CLASSES_ROOT
+ #else
+ HKEY_CURRENT_USER
+ #endif
+ , szSubkey));
+ }
+
+ return hr;
+}
diff --git a/catchcopy-windows-explorer-plugin/Reg.h b/catchcopy-windows-explorer-plugin/Reg.h new file mode 100755 index 0000000..6bc9a26 --- /dev/null +++ b/catchcopy-windows-explorer-plugin/Reg.h @@ -0,0 +1,103 @@ +#ifndef _REG_H_
+#define _REG_H_
+#pragma once
+
+//#define CATCHCOPY_ROOT_MODE
+
+#include <windows.h>
+#include <winreg.h>
+//
+// FUNCTION: RegisterInprocServer
+//
+// PURPOSE: Register the in-process component in the registry.
+//
+// PARAMETERS:
+// * pszModule - Path of the module that contains the component
+// * clsid - Class ID of the component
+// * pszFriendlyName - Friendly name
+// * pszThreadModel - Threading model
+//
+// NOTE: The function creates the HKCR\CLSID\{<CLSID>} key in the registry.
+//
+// HKCR
+// {
+// NoRemove CLSID
+// {
+// ForceRemove {<CLSID>} = s '<Friendly Name>'
+// {
+// InprocServer32 = s '%MODULE%'
+// {
+// val ThreadingModel = s '<Thread Model>'
+// }
+// }
+// }
+// }
+//
+HRESULT RegisterInprocServer(PCWSTR pszModule, const CLSID& clsid,
+ PCWSTR pszFriendlyName, PCWSTR pszThreadModel);
+
+
+//
+// FUNCTION: UnregisterInprocServer
+//
+// PURPOSE: Unegister the in-process component in the registry.
+//
+// PARAMETERS:
+// * clsid - Class ID of the component
+//
+// NOTE: The function deletes the HKCR\CLSID\{<CLSID>} key in the registry.
+//
+HRESULT UnregisterInprocServer(const CLSID& clsid);
+
+
+//
+// FUNCTION: RegisterShellExtContextMenuHandler
+//
+// PURPOSE: Register the context menu handler.
+//
+// PARAMETERS:
+// * pszFileType - The file type that the context menu handler is
+// associated with. For example, '*' means all file types; '.txt' means
+// all .txt files. The parameter must not be NULL.
+// * clsid - Class ID of the component
+// * pszFriendlyName - Friendly name
+//
+// NOTE: The function creates the following key in the registry.
+//
+// HKCR
+// {
+// NoRemove <File Type>
+// {
+// NoRemove shellex
+// {
+// NoRemove ContextMenuHandlers
+// {
+// {<CLSID>} = s '<Friendly Name>'
+// }
+// }
+// }
+// }
+//
+HRESULT RegisterShellExtContextMenuHandler(
+ PCWSTR pszFileType, const CLSID& clsid, PCWSTR pszFriendlyName);
+
+
+//
+// FUNCTION: UnregisterShellExtContextMenuHandler
+//
+// PURPOSE: Unregister the context menu handler.
+//
+// PARAMETERS:
+// * pszFileType - The file type that the context menu handler is
+// associated with. For example, '*' means all file types; '.txt' means
+// all .txt files. The parameter must not be NULL.
+// * clsid - Class ID of the component
+//
+// NOTE: The function removes the {<CLSID>} key under
+// HKCR\<File Type>\shellex\ContextMenuHandlers in the registry.
+//
+HRESULT UnregisterShellExtContextMenuHandler(
+ PCWSTR pszFileType, const CLSID& clsid);
+
+LONG RecursiveDeleteKey(HKEY hKeyParent, PCWSTR szKeyChild);
+#endif //_REG_H_
diff --git a/catchcopy-windows-explorer-plugin/Variable.h b/catchcopy-windows-explorer-plugin/Variable.h new file mode 100755 index 0000000..292e2a0 --- /dev/null +++ b/catchcopy-windows-explorer-plugin/Variable.h @@ -0,0 +1,7 @@ +#ifndef VARIABLE_H
+#define VARIABLE_H
+
+/// \brief Un-comment this next line to put ultracopier in debug mode
+//#define CATCHCOPY_EXPLORER_PLUGIN_DEBUG
+
+#endif // VARIABLE_H
diff --git a/catchcopy-windows-explorer-plugin/resource.h b/catchcopy-windows-explorer-plugin/resource.h new file mode 100755 index 0000000..4823355 --- /dev/null +++ b/catchcopy-windows-explorer-plugin/resource.h @@ -0,0 +1,18 @@ +//{{NO_DEPENDENCIES}}
+// Microsoft Visual C++ generated include file.
+// Used by CatchCopy.rc
+//
+#define IDS_PROJNAME 100
+#define IDR_CATCHCOPY 101
+#define IDR_DDSHELLEXT 102
+
+// Next default values for new objects
+//
+#ifdef APSTUDIO_INVOKED
+#ifndef APSTUDIO_READONLY_SYMBOLS
+#define _APS_NEXT_RESOURCE_VALUE 201
+#define _APS_NEXT_COMMAND_VALUE 32768
+#define _APS_NEXT_CONTROL_VALUE 201
+#define _APS_NEXT_SYMED_VALUE 103
+#endif
+#endif
|