⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 shellext.cpp

📁 FastCopy 利用缓冲技术加快文件拷贝
💻 CPP
📖 第 1 页 / 共 2 页
字号:
static char *shellext_id = 
	"@(#)Copyright (C) H.Shirouzu 2005   shellext.cpp	Ver1.21";
/* ========================================================================
	Project  Name			: Shell Extension for Fast Copy
	Create					: 2005-01-23(Sun)
	Update					: 2005-07-06(Wed)
	Copyright				: H.Shirouzu
	Reference				: 
	======================================================================== */

#include "..\tlib.h"
#include <olectl.h>
#include "resource.h"

#pragma data_seg(".text")
#define INITGUID
#include <initguid.h>
#include <shlguid.h>
#include "shellext.h"
#pragma data_seg()

ShellExtSystem	*SysObj = NULL;

// 儗僕僗僩儕搊榐僉乕乮Ref: tortoise subversion乯
char	*DllRegKeys[] = {
	"*\\shellex\\ContextMenuHandlers",
	"*\\shellex\\DragDropHandlers",
	"Folder\\shellex\\ContextMenuHandlers",
	"Folder\\shellex\\DragDropHandlers",
	"Directory\\shellex\\ContextMenuHandlers",
	"Directory\\Background\\shellex\\ContextMenuHandlers",
	"Directory\\shellex\\DragDropHandlers",
	"Drive\\shellex\\ContextMenuHandlers",
	"Drive\\shellex\\DragDropHandlers",
	"InternetShortcut\\shellex\\ContextMenuHandlers",
	"lnkfile\\shellex\\ContextMenuHandlers",
	NULL
};

UINT (WINAPI *DragQueryFileV)(HDROP, UINT, void *, UINT);
BOOL (WINAPI *SHGetPathFromIDListV)(LPCITEMIDLIST, void *);
int (*strlenV)(const void *);
int (WINAPI *wsprintfV)(void *, const void *,...);
int (*MakePathV)(void *, const void *, const void *);
int		CHAR_LEN_V;
BOOL	IS_WINNT_V;
void	*EMPTY_STR_V;
void	*FMT_TOSTR_V;

/*=========================================================================
  僋儔僗 丗 ShellExt
  奣  梫 丗 僔僃儖奼挘僋儔僗
  愢  柧 丗 
  拲  堄 丗 
=========================================================================*/
ShellExt::ShellExt(void)
{
	cmdFirst = cmdLast = 0;
	refCnt = 0;
	dataObj = NULL;
	if (SysObj)
		SysObj->DllRefCnt++;
}

ShellExt::~ShellExt()
{
	if (dataObj)
		dataObj->Release();
	if (SysObj)
		SysObj->DllRefCnt--;
}

STDMETHODIMP ShellExt::Initialize(const ITEMIDLIST *pIDFolder, IDataObject *pDataObj, HKEY hRegKey)
{
	srcArray.Init();
	dstArray.Init();

	if (dataObj)
		dataObj->Release();

	if (!pDataObj)
		return E_FAIL;

	dataObj = pDataObj;
	pDataObj->AddRef();

	STGMEDIUM	medium;
	FORMATETC	fe = { CF_HDROP, NULL, DVASPECT_CONTENT, -1, TYMED_HGLOBAL };

	if (pDataObj->GetData(&fe, &medium) < 0)
		return E_INVALIDARG;

	WCHAR	path[MAX_PATH_EX];

	HDROP	hDrop = (HDROP)::GlobalLock(medium.hGlobal);
	int max = DragQueryFileV(hDrop, 0xffffffff, NULL, 0);

	for (int i=0; i < max; i++) {
		DragQueryFileV(hDrop, i, path, sizeof(path) / CHAR_LEN_V);
		srcArray.RegisterPath(path);
	}
	::GlobalUnlock(medium.hGlobal);
	::ReleaseStgMedium(&medium);

	if (pIDFolder && SHGetPathFromIDListV(pIDFolder, path)) {
		dstArray.RegisterPath(path);
	}

	return	NOERROR;
}

STDMETHODIMP ShellExt::QueryInterface(REFIID riid, void **ppv)
{
	*ppv = NULL;

	if (IsEqualIID(riid, IID_IShellExtInit) || IsEqualIID(riid, IID_IUnknown)) {
		*ppv = (IShellExtInit *)this;
	}
	else if (IsEqualIID(riid, IID_IContextMenu)) {
		*ppv = (IContextMenu *)this;
	}

	if (*ppv) {
		AddRef();
		return NOERROR;
	}

	return E_NOINTERFACE;
}

STDMETHODIMP ShellExt::QueryContextMenu(HMENU hMenu, UINT iMenu, UINT _cmdFirst, UINT _cmdLast, UINT flg)
{
	HMENU	hTargetMenu = hMenu;
	BOOL	is_dd = dstArray.Num();
	int		menu_flags = GetMenuFlags();
	int		mask_menu_flags = (menu_flags & (is_dd ? SHEXT_DD_MENUS : SHEXT_RIGHT_MENUS));
	BOOL	is_submenu = (menu_flags & (is_dd ? SHEXT_SUBMENU_DD : SHEXT_SUBMENU_RIGHT));
	BOOL	is_separator = (menu_flags & SHEXT_SUBMENU_NOSEP) ? FALSE : TRUE;

	if (!is_dd && (flg == CMF_NORMAL) || (flg & (CMF_VERBSONLY|CMF_DEFAULTONLY))) {
		return	ResultFromScode(MAKE_SCODE(SEVERITY_SUCCESS, 0, 0));
	}

	cmdFirst = cmdLast = _cmdFirst;
	// 儊僯儏乕傾僀僥儉偺捛壛
	if (mask_menu_flags && srcArray.Num() > 0) {
		if (!is_dd && is_separator)
			::InsertMenu(hMenu, iMenu++, MF_SEPARATOR|MF_BYPOSITION, 0, 0);

		if (is_separator)
			::InsertMenu(hMenu, iMenu, MF_SEPARATOR|MF_BYPOSITION, 0, 0);

		if (is_submenu) {
			hTargetMenu = ::CreatePopupMenu();
			::InsertMenu(hMenu, iMenu, MF_POPUP|MF_BYPOSITION, (UINT)hTargetMenu, FASTCOPY);
			iMenu = 0;
		}
		if (mask_menu_flags & (SHEXT_RIGHT_COPY|SHEXT_DD_COPY)) {
			::InsertMenu(hTargetMenu, iMenu++, MF_STRING|MF_BYPOSITION, cmdLast, is_dd ? GetLoadStr(IDS_DDCOPY) : GetLoadStr(IDS_RIGHTCOPY));
		}
		cmdLast++;

		if (mask_menu_flags & (SHEXT_RIGHT_DELETE|SHEXT_DD_MOVE)) {
			::InsertMenu(hTargetMenu, iMenu++, MF_STRING|MF_BYPOSITION, cmdLast, is_dd ? GetLoadStr(IDS_DDMOVE) : GetLoadStr(IDS_RIGHTDEL));
		}
		cmdLast++;
	}

	return	ResultFromScode(MAKE_SCODE(SEVERITY_SUCCESS, 0, cmdLast - cmdFirst));
}

STDMETHODIMP ShellExt::InvokeCommand(CMINVOKECOMMANDINFO *info)
{
	int		cmd = LOWORD(info->lpVerb);

	if (cmd >= 0 && cmd <= 1 && srcArray.Num() > 0) {
		HANDLE	hRead, hWrite;
		SECURITY_ATTRIBUTES sa = { sizeof(SECURITY_ATTRIBUTES), 0, TRUE };

		::CreatePipe(&hRead, &hWrite, &sa, 0);
		::DuplicateHandle(::GetCurrentProcess(), hWrite, ::GetCurrentProcess(), &hWrite, 0, FALSE, DUPLICATE_CLOSE_SOURCE|DUPLICATE_SAME_ACCESS);

		STARTUPINFO			st_info;
		memset(&st_info, 0, sizeof(st_info));
		st_info.cb = sizeof(st_info);
		st_info.dwFlags = STARTF_USESTDHANDLES;
		st_info.hStdInput = hRead;
		st_info.hStdOutput = ::GetStdHandle(STD_OUTPUT_HANDLE);
		st_info.hStdError = ::GetStdHandle(STD_ERROR_HANDLE);

		BOOL	is_dd = dstArray.Num();
		char	arg[MAX_PATH_EX];
		PROCESS_INFORMATION	pr_info;

		wsprintf(arg, "\"%s\" %s %s", SysObj->ExeName, cmd == 1 ? is_dd ? "/cmd=move" : "/cmd=delete" : "", SHELLEXT_OPT);
		BOOL ret = ::CreateProcess(SysObj->ExeName, arg, 0, 0, TRUE, CREATE_DEFAULT_ERROR_MODE, 0, 0, &st_info, &pr_info);
		::CloseHandle(hRead);

		if (ret) {
			DWORD	len = srcArray.GetMultiPathLen();
			WCHAR	*buf = new WCHAR[max(len, MAX_PATH_EX)];
			// dstArray 偑柍偄応崌偼丄\0 傑偱弌椡
			len = srcArray.GetMultiPath(buf, len) + (!is_dd ? 1 : 0);
			::WriteFile(hWrite, buf, len * CHAR_LEN_V, &len, 0);

			if (is_dd) {
				WCHAR	dir[MAX_PATH_EX];
				MakePathV(dir, dstArray.Path(0), EMPTY_STR_V);	// 枛旜偵 \\ 傪晅梌
				len = wsprintfV(buf, FMT_TOSTR_V, dir) + 1;
				::WriteFile(hWrite, buf, len * CHAR_LEN_V, &len, 0);
			}
			delete [] buf;
			::CloseHandle(pr_info.hProcess);
			::CloseHandle(pr_info.hThread);
		}
		::CloseHandle(hWrite);
		return NOERROR;
	}
	return	E_INVALIDARG;
}

STDMETHODIMP ShellExt::GetCommandString(UINT cmd, UINT flg, UINT *, char *name, UINT cchMax)
{
	BOOL	is_dd = dstArray.Num();

	if (flg == GCS_HELPTEXT) {
		switch (cmd) {
		case 0:
			strncpy(name, is_dd ? GetLoadStr(IDS_DDCOPY) : GetLoadStr(IDS_RIGHTCOPY), cchMax);
			return	S_OK;
		case 1:
			strncpy(name, is_dd ? GetLoadStr(IDS_DDMOVE) : GetLoadStr(IDS_RIGHTDEL), cchMax);
			return	S_OK;
		}
	}
    return E_INVALIDARG;
}

STDMETHODIMP_(ULONG) ShellExt::AddRef()
{
	return ++refCnt;
}

STDMETHODIMP_(ULONG) ShellExt::Release()
{
	if (--refCnt)
		return refCnt;

	delete this;
	return	0;
}


/*=========================================================================
  僋儔僗 丗 ShellExtClassFactory
  奣  梫 丗 僔僃儖奼挘僋儔僗
  愢  柧 丗 
  拲  堄 丗 
=========================================================================*/
ShellExtClassFactory::ShellExtClassFactory(void)
{
	refCnt = 0;
	if (SysObj)
		SysObj->DllRefCnt++;
}

ShellExtClassFactory::~ShellExtClassFactory()
{
	if (SysObj)
		SysObj->DllRefCnt--;
}

STDMETHODIMP ShellExtClassFactory::CreateInstance(IUnknown *pUnkOuter, REFIID riid, void **ppvObj)
{
	*ppvObj = NULL;

	if (pUnkOuter)
		return CLASS_E_NOAGGREGATION;

	ShellExt *shellExt = new ShellExt;
	if (NULL == shellExt)
		return E_OUTOFMEMORY;

	return shellExt->QueryInterface(riid, ppvObj);
}

STDMETHODIMP ShellExtClassFactory::LockServer(BOOL fLock)
{
	return NOERROR;
}

STDMETHODIMP ShellExtClassFactory::QueryInterface(REFIID riid, void **ppv)
{
	*ppv = NULL;

	if (IsEqualIID(riid, IID_IUnknown) || IsEqualIID(riid, IID_IClassFactory)) {
		*ppv = (IClassFactory *)this;
		AddRef();
		return NOERROR;
	}
	return E_NOINTERFACE;
}

STDMETHODIMP_(ULONG) ShellExtClassFactory::AddRef()
{
	return ++refCnt;
}

STDMETHODIMP_(ULONG) ShellExtClassFactory::Release()
{
	if (--refCnt)
		return refCnt;
	delete this;
	return 0;

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -