打开APP
userphoto
未登录

开通VIP,畅享免费电子书等14项超值服

开通VIP
BHOサンプル
EternalWindows
BHO / BHOサンプル

BHOのサンプルコードを示します。まず、DLLのdefファイルを示します。

LIBRARY	"mydll"EXPORTS	DllCanUnloadNow PRIVATE	DllGetClassObject PRIVATE	DllRegisterServer PRIVATE	DllUnregisterServer PRIVATE

次に、sample.hを示します。

class CBho : public IObjectWithSite, public IDispatch{public:	STDMETHODIMP QueryInterface(REFIID riid, void **ppvObject);	STDMETHODIMP_(ULONG) AddRef();	STDMETHODIMP_(ULONG) Release();		STDMETHODIMP SetSite(IUnknown *pUnkSite);	STDMETHODIMP GetSite(REFIID riid, void **ppvSite);	STDMETHODIMP GetTypeInfoCount(UINT *pctinfo);	STDMETHODIMP GetTypeInfo(UINT iTInfo, LCID lcid, ITypeInfo **ppTInfo);	STDMETHODIMP GetIDsOfNames(REFIID riid, LPOLESTR *rgszNames, UINT cNames, LCID lcid, DISPID *rgDispId);	STDMETHODIMP Invoke(DISPID dispIdMember, REFIID riid, LCID lcid, WORD wFlags, DISPPARAMS *pDispParams, VARIANT *pVarResult, EXCEPINFO *pExcepInfo, UINT *puArgErr);		CBho();	~CBho();private:	HINTERNET OpenInternetSession();private:	LONG               m_cRef;	IUnknown           *m_pSite;	IWebBrowser2       *m_pWebBrowser2;	IConnectionPoint   *m_pConnectionPoint;	DWORD              m_dwCookie;	CMouseMoveListener *m_pMouseMoveListener;	HINTERNET          m_hSession;};class CClassFactory : public IClassFactory{public:	STDMETHODIMP QueryInterface(REFIID riid, void **ppvObject);	STDMETHODIMP_(ULONG) AddRef();	STDMETHODIMP_(ULONG) Release();		STDMETHODIMP CreateInstance(IUnknown *pUnkOuter, REFIID riid, void **ppvObject);	STDMETHODIMP LockServer(BOOL fLock);};

次に、mousemove.hを示します。

class CMouseMoveListener : public IDispatch{public:	STDMETHODIMP QueryInterface(REFIID riid, void **ppvObject);	STDMETHODIMP_(ULONG) AddRef();	STDMETHODIMP_(ULONG) Release();		STDMETHODIMP GetTypeInfoCount(UINT *pctinfo);	STDMETHODIMP GetTypeInfo(UINT iTInfo, LCID lcid, ITypeInfo **ppTInfo);	STDMETHODIMP GetIDsOfNames(REFIID riid, LPOLESTR *rgszNames, UINT cNames, LCID lcid, DISPID *rgDispId);	STDMETHODIMP Invoke(DISPID dispIdMember, REFIID riid, LCID lcid, WORD wFlags, DISPPARAMS *pDispParams, VARIANT *pVarResult, EXCEPINFO *pExcepInfo, UINT *puArgErr);		CMouseMoveListener(IWebBrowser2 *pWebBrowser2, HINTERNET hSession);	~CMouseMoveListener();private:	void CreatePopup();	BOOL SendRequest(LPWSTR lpszUrl, LPBYTE lpBuffer, DWORD dwBufferSize);	private:	LONG           m_cRef;	HWND           m_hwndParent;	HWND           m_hwndPopup;	IWebBrowser2   *m_pWebBrowser2;	IHTMLDocument2 *m_pDocument2;	HINTERNET      m_hSession;	BSTR           m_bstrHrefPrev;};

次に、ソースファイル(CBhoの実装)を示します。

#include <windows.h>#include <shlwapi.h>#include <shlobj.h>#include <mshtml.h>#include <exdispid.h>#include <wininet.h>#include "mousemove.h"#include "sample.h"#pragma comment (lib, "shlwapi.lib")#pragma comment (lib, "urlmon.lib")#pragma comment (lib, "wininet.lib")const CLSID CLSID_BhoSample = {0x5b10edef, 0xb228, 0x4629, {0x8e, 0x82, 0x34, 0xe0, 0x69, 0xc8, 0x60, 0x80}};const TCHAR g_szClsid[] = TEXT("{5B10EDEF-B228-4629-8E82-34E069C86080}");LONG      g_lLocks = 0;HINSTANCE g_hinstDll = NULL;void LockModule(BOOL bLock);BOOL CreateRegistryKey(HKEY hKeyRoot, LPTSTR lpszKey, LPTSTR lpszValue, LPTSTR lpszData);BOOL CreateRegistryKeyDword(HKEY hKeyRoot, LPTSTR lpszKey, LPTSTR lpszValue, LPDWORD lpdw);// CBhoCBho::CBho(){	m_cRef = 1;	m_pSite = NULL;	m_pWebBrowser2 = NULL;	m_pConnectionPoint = 0;	m_dwCookie = 0;	m_pMouseMoveListener = NULL;	m_hSession = NULL;	LockModule(TRUE);}CBho::~CBho(){	LockModule(FALSE);}STDMETHODIMP CBho::QueryInterface(REFIID riid, void **ppvObject){	*ppvObject = NULL;	if (IsEqualIID(riid, IID_IUnknown) || IsEqualIID(riid, IID_IObjectWithSite))		*ppvObject = static_cast<IObjectWithSite *>(this);	else if (IsEqualIID(riid, IID_IDispatch) || IsEqualIID(riid, DIID_DWebBrowserEvents2))		*ppvObject = static_cast<IDispatch *>(this);	else		return E_NOINTERFACE;	AddRef();	return S_OK;}STDMETHODIMP_(ULONG) CBho::AddRef(){	return InterlockedIncrement(&m_cRef);}STDMETHODIMP_(ULONG) CBho::Release(){	if (InterlockedDecrement(&m_cRef) == 0) {		delete this;		return 0;	}	return m_cRef;}STDMETHODIMP CBho::SetSite(IUnknown *pUnkSite){	HRESULT hr = S_OK;		if (m_pSite != NULL){		m_pSite->Release();		m_pSite = NULL;	}	if (pUnkSite != NULL) {		IConnectionPointContainer *pConnectionPointContainer;				m_pSite = pUnkSite;		m_pSite->AddRef();				IUnknown_QueryService(pUnkSite, SID_SWebBrowserApp, IID_PPV_ARGS(&m_pWebBrowser2));		hr = m_pWebBrowser2->QueryInterface(IID_PPV_ARGS(&pConnectionPointContainer));		if (FAILED(hr))			return hr;				pConnectionPointContainer->FindConnectionPoint(DIID_DWebBrowserEvents2, &m_pConnectionPoint);		pConnectionPointContainer->Release();		m_pConnectionPoint->Advise(static_cast<IDispatch *>(this), &m_dwCookie);				m_hSession = OpenInternetSession();		return S_OK;	}	else {		if (m_hSession != NULL)			InternetCloseHandle(m_hSession);		if (m_pMouseMoveListener != NULL)			m_pMouseMoveListener->Release();				if (m_pConnectionPoint != NULL) {			m_pConnectionPoint->Unadvise(m_dwCookie);			m_pConnectionPoint->Release();		}		if (m_pWebBrowser2 != NULL)			m_pWebBrowser2->Release();	}	return hr;}STDMETHODIMP CBho::GetSite(REFIID riid, void **ppvSite){	HRESULT hr;	*ppvSite = NULL;	if (m_pSite != NULL)		hr = m_pSite->QueryInterface(riid, ppvSite);	else		hr = E_FAIL;	return hr;}STDMETHODIMP CBho::GetTypeInfoCount(UINT *pctinfo){	*pctinfo = 0;		return S_OK;}STDMETHODIMP CBho::GetTypeInfo(UINT iTInfo, LCID lcid, ITypeInfo **ppTInfo){	return E_NOTIMPL;}STDMETHODIMP CBho::GetIDsOfNames(REFIID riid, LPOLESTR *rgszNames, UINT cNames, LCID lcid, DISPID *rgDispId){	return E_NOTIMPL;}STDMETHODIMP CBho::Invoke(DISPID dispIdMember, REFIID riid, LCID lcid, WORD wFlags, DISPPARAMS *pDispParams, VARIANT *pVarResult, EXCEPINFO *pExcepInfo, UINT *puArgErr){	if (dispIdMember == DISPID_NAVIGATECOMPLETE2) {		IHTMLDocument2 *pDocument2;		IDispatch      *pDispatch;		VARIANT        varDispatch;		m_pWebBrowser2->get_Document(&pDispatch);		pDispatch->QueryInterface(IID_PPV_ARGS(&pDocument2));		pDispatch->Release();		if (m_pMouseMoveListener != NULL)			m_pMouseMoveListener->Release();		m_pMouseMoveListener = new CMouseMoveListener(m_pWebBrowser2, m_hSession);				varDispatch.vt = VT_DISPATCH;		varDispatch.pdispVal = m_pMouseMoveListener;		pDocument2->put_onmousemove(varDispatch);		pDocument2->Release();	}	else		return DISP_E_MEMBERNOTFOUND;	return S_OK;}HINTERNET CBho::OpenInternetSession(){	CHAR      szUserAgentA[256];	WCHAR     szUserAgentW[256];	DWORD     dwLength;	HINTERNET hSession;	DWORD     dwTimeOut;		UrlMkGetSessionOption(URLMON_OPTION_USERAGENT, szUserAgentA, sizeof(szUserAgentA), &dwLength, 0);		#ifdef UNICODE	MultiByteToWideChar(CP_ACP, 0, szUserAgentA, -1, szUserAgentW, 256);	hSession = InternetOpen(szUserAgentW, INTERNET_OPEN_TYPE_PRECONFIG, NULL, NULL, 0);#else	hSession = InternetOpen(szUserAgentA, INTERNET_OPEN_TYPE_PRECONFIG, NULL, NULL, 0);#endif		dwTimeOut = 2 * 1000;	InternetSetOption(hSession, INTERNET_OPTION_RECEIVE_TIMEOUT, &dwTimeOut, sizeof(DWORD));	return hSession;}// CClassFactorySTDMETHODIMP CClassFactory::QueryInterface(REFIID riid, void **ppvObject){	*ppvObject = NULL;	if (IsEqualIID(riid, IID_IUnknown) || IsEqualIID(riid, IID_IClassFactory))		*ppvObject = static_cast<IClassFactory *>(this);	else		return E_NOINTERFACE;	AddRef();		return S_OK;}STDMETHODIMP_(ULONG) CClassFactory::AddRef(){	LockModule(TRUE);	return 2;}STDMETHODIMP_(ULONG) CClassFactory::Release(){	LockModule(FALSE);	return 1;}STDMETHODIMP CClassFactory::CreateInstance(IUnknown *pUnkOuter, REFIID riid, void **ppvObject){	CBho    *p;	HRESULT hr;		*ppvObject = NULL;	if (pUnkOuter != NULL)		return CLASS_E_NOAGGREGATION;	p = new CBho();	if (p == NULL)		return E_OUTOFMEMORY;	hr = p->QueryInterface(riid, ppvObject);	p->Release();	return hr;}STDMETHODIMP CClassFactory::LockServer(BOOL fLock){	LockModule(fLock);	return S_OK;}// DLL ExportSTDAPI DllCanUnloadNow(void){	return g_lLocks == 0 ? S_OK : S_FALSE;}STDAPI DllGetClassObject(REFCLSID rclsid, REFIID riid, LPVOID *ppv){	static CClassFactory serverFactory;	HRESULT hr;		*ppv = NULL;	if (IsEqualCLSID(rclsid, CLSID_BhoSample))		hr = serverFactory.QueryInterface(riid, ppv);	else		hr = CLASS_E_CLASSNOTAVAILABLE;	return hr;}STDAPI DllRegisterServer(void){	TCHAR szModulePath[MAX_PATH];	TCHAR szKey[256];	DWORD dwValue;	wsprintf(szKey, TEXT("CLSID\\%s"), g_szClsid);	if (!CreateRegistryKey(HKEY_CLASSES_ROOT, szKey, NULL, TEXT("BHO Sample")))		return E_FAIL;	GetModuleFileName(g_hinstDll, szModulePath, sizeof(szModulePath) / sizeof(TCHAR));	wsprintf(szKey, TEXT("CLSID\\%s\\InprocServer32"), g_szClsid);	if (!CreateRegistryKey(HKEY_CLASSES_ROOT, szKey, NULL, szModulePath))		return E_FAIL;		wsprintf(szKey, TEXT("CLSID\\%s\\InprocServer32"), g_szClsid);	if (!CreateRegistryKey(HKEY_CLASSES_ROOT, szKey, TEXT("ThreadingModel"), TEXT("Apartment")))		return E_FAIL;	wsprintf(szKey, TEXT("SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\explorer\\Browser Helper Objects\\%s"), g_szClsid);	if (!CreateRegistryKey(HKEY_LOCAL_MACHINE, szKey, NULL, NULL))		return E_FAIL;	dwValue = 1;	wsprintf(szKey, TEXT("SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\explorer\\Browser Helper Objects\\%s"), g_szClsid);	if (!CreateRegistryKeyDword(HKEY_LOCAL_MACHINE, szKey, TEXT("NoExplorer"), &dwValue))		return E_FAIL;	return S_OK;}STDAPI DllUnregisterServer(void){	TCHAR szKey[256];	wsprintf(szKey, TEXT("CLSID\\%s"), g_szClsid);	SHDeleteKey(HKEY_CLASSES_ROOT, szKey);	wsprintf(szKey, TEXT("SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\explorer\\Browser Helper Objects\\%s"), g_szClsid);	SHDeleteKey(HKEY_LOCAL_MACHINE, szKey);	return S_OK;}BOOL WINAPI DllMain(HINSTANCE hinstDll, DWORD dwReason, LPVOID lpReserved){	switch (dwReason) {	case DLL_PROCESS_ATTACH:		g_hinstDll = hinstDll;		DisableThreadLibraryCalls(hinstDll);		return TRUE;	}	return TRUE;}// Functionvoid LockModule(BOOL bLock){	if (bLock)		InterlockedIncrement(&g_lLocks);	else		InterlockedDecrement(&g_lLocks);}BOOL CreateRegistryKey(HKEY hKeyRoot, LPTSTR lpszKey, LPTSTR lpszValue, LPTSTR lpszData){	HKEY  hKey;	LONG  lResult;	DWORD dwSize;	lResult = RegCreateKeyEx(hKeyRoot, lpszKey, 0, NULL, REG_OPTION_NON_VOLATILE, KEY_WRITE, NULL, &hKey, NULL);	if (lResult != ERROR_SUCCESS)		return FALSE;	if (lpszData != NULL)		dwSize = (lstrlen(lpszData) + 1) * sizeof(TCHAR);	else		dwSize = 0;	RegSetValueEx(hKey, lpszValue, 0, REG_SZ, (LPBYTE)lpszData, dwSize);	RegCloseKey(hKey);		return TRUE;}BOOL CreateRegistryKeyDword(HKEY hKeyRoot, LPTSTR lpszKey, LPTSTR lpszValue, LPDWORD lpdw){	HKEY hKey;	LONG lResult;	lResult = RegCreateKeyEx(hKeyRoot, lpszKey, 0, NULL, REG_OPTION_NON_VOLATILE, KEY_WRITE, NULL, &hKey, NULL);	if (lResult != ERROR_SUCCESS)		return FALSE;	RegSetValueEx(hKey, lpszValue, 0, REG_DWORD, (LPBYTE)lpdw, sizeof(DWORD));	RegCloseKey(hKey);		return TRUE;}

次に、ソースファイル(CMouseMoveListenerの実装)を示します。

#include <windows.h>#include <shlwapi.h>#include <shlobj.h>#include <mshtml.h>#include <wininet.h>#include "mousemove.h"CMouseMoveListener::CMouseMoveListener(IWebBrowser2 *pWebBrowser2, HINTERNET hSession){	IDispatch *pDispatch;		m_cRef = 1;	m_hwndParent = NULL;	m_hwndPopup = NULL;	m_pWebBrowser2 = pWebBrowser2;	m_hSession = hSession;	m_bstrHrefPrev = NULL;	m_pWebBrowser2->get_Document(&pDispatch);	pDispatch->QueryInterface(IID_PPV_ARGS(&m_pDocument2));	pDispatch->Release();	CreatePopup();}CMouseMoveListener::~CMouseMoveListener(){	m_pDocument2->Release();	DestroyWindow(m_hwndPopup);}STDMETHODIMP CMouseMoveListener::QueryInterface(REFIID riid, void **ppvObject){	*ppvObject = NULL;	if (IsEqualIID(riid, IID_IUnknown) || IsEqualIID(riid, IID_IDispatch))		*ppvObject = static_cast<IDispatch *>(this);	else		return E_NOINTERFACE;	AddRef();		return S_OK;}STDMETHODIMP_(ULONG) CMouseMoveListener::AddRef(){	return InterlockedIncrement(&m_cRef);}STDMETHODIMP_(ULONG) CMouseMoveListener::Release(){	if (InterlockedDecrement(&m_cRef) == 0) {			delete this;		return 0;	}	return m_cRef;}STDMETHODIMP CMouseMoveListener::GetTypeInfoCount(UINT *pctinfo){	*pctinfo = 0;		return S_OK;}STDMETHODIMP CMouseMoveListener::GetTypeInfo(UINT iTInfo, LCID lcid, ITypeInfo **ppTInfo){	return E_NOTIMPL;}STDMETHODIMP CMouseMoveListener::GetIDsOfNames(REFIID riid, LPOLESTR *rgszNames, UINT cNames, LCID lcid, DISPID *rgDispId){	return E_NOTIMPL;}STDMETHODIMP CMouseMoveListener::Invoke(DISPID dispIdMember, REFIID riid, LCID lcid, WORD wFlags, DISPPARAMS *pDispParams, VARIANT *pVarResult, EXCEPINFO *pExcepInfo, UINT *puArgErr){	POINT              pt;	BSTR               bstrUrl, bstrHref;	IHTMLElement       *pElement;	IHTMLAnchorElement *pAnchorElement;	CHAR               szText[4096];	GetCursorPos(&pt);	ScreenToClient(m_hwndParent, &pt);	m_pDocument2->elementFromPoint(pt.x, pt.y, &pElement);	if (pElement == NULL) {		ShowWindow(m_hwndPopup, SW_HIDE);		SysFreeString(m_bstrHrefPrev);		m_bstrHrefPrev = NULL;		return E_FAIL;	}	pElement->QueryInterface(IID_PPV_ARGS(&pAnchorElement));	pElement->Release();	if (pAnchorElement == NULL) {		ShowWindow(m_hwndPopup, SW_HIDE);		SysFreeString(m_bstrHrefPrev);		m_bstrHrefPrev = NULL;		return E_FAIL;	}		pAnchorElement->get_href(&bstrHref);	if (lstrcmpW(bstrHref, m_bstrHrefPrev) == 0) {		pAnchorElement->Release();		return S_OK;	}	m_bstrHrefPrev = bstrHref;	if (PathIsURL(bstrHref))		bstrUrl = SysAllocString(bstrHref);	else {		m_pDocument2->get_URL(&bstrUrl);		PathRemoveFileSpec(bstrUrl);		lstrcat(bstrUrl, bstrHref);	}	if (SendRequest(bstrUrl, (LPBYTE)szText, sizeof(szText)))		SetWindowTextA(m_hwndPopup, szText);	else		SetWindowTextA(m_hwndPopup, "error");	MoveWindow(m_hwndPopup, pt.x, pt.y, 600, 500, TRUE);	ShowWindow(m_hwndPopup, SW_SHOW);		SysFreeString(bstrUrl);	pAnchorElement->Release();	return S_OK;}void CMouseMoveListener::CreatePopup(){	IShellBrowser *pShellBrowser;	IUnknown_QueryService(m_pWebBrowser2, SID_STopLevelBrowser, IID_PPV_ARGS(&pShellBrowser));	IUnknown_GetWindow(pShellBrowser, &m_hwndParent);	m_hwndPopup = CreateWindowEx(0, TEXT("STATIC"), TEXT(""), WS_CHILD, 0, 0, 0, 0, m_hwndParent, (HMENU)1, 0, NULL);	pShellBrowser->Release();}BOOL CMouseMoveListener::SendRequest(LPWSTR lpszUrl, LPBYTE lpBuffer, DWORD dwBufferSize){	HINTERNET       hConnect, hRequest;	URL_COMPONENTSW urlComponents;	WCHAR           szHostName[INTERNET_MAX_HOST_NAME_LENGTH], szUrlPath[INTERNET_MAX_PATH_LENGTH];	DWORD           dwSize;	DWORD           dwStatusCode;	ZeroMemory(&urlComponents, sizeof(URL_COMPONENTSW));	urlComponents.dwStructSize     = sizeof(URL_COMPONENTSW);	urlComponents.lpszHostName     = szHostName;	urlComponents.dwHostNameLength = sizeof(szHostName) / sizeof(WCHAR);	urlComponents.lpszUrlPath      = szUrlPath;	urlComponents.dwUrlPathLength  = sizeof(szUrlPath) / sizeof(WCHAR);	if (!InternetCrackUrlW(lpszUrl, lstrlen(lpszUrl), 0, &urlComponents))		return FALSE;	hConnect = InternetConnectW(m_hSession, szHostName, urlComponents.nPort, NULL, NULL, INTERNET_SERVICE_HTTP, 0, 0);	if (hConnect == NULL)		return FALSE;	hRequest = HttpOpenRequestW(hConnect, L"GET", szUrlPath, NULL, NULL, NULL, 0,  0);	if (hRequest == NULL) {		InternetCloseHandle(hConnect);		return FALSE;	}	if (!HttpSendRequest(hRequest, NULL, 0, NULL, 0)) {		InternetCloseHandle(hRequest);		InternetCloseHandle(hConnect);		return FALSE;	}	dwSize = sizeof(DWORD);	HttpQueryInfo(hRequest, HTTP_QUERY_STATUS_CODE | HTTP_QUERY_FLAG_NUMBER, &dwStatusCode, &dwSize, NULL);	if (dwStatusCode == HTTP_STATUS_OK){		DWORD dwRead = 0;		InternetReadFile(hRequest, lpBuffer, dwBufferSize, &dwRead);	}	InternetCloseHandle(hRequest);	InternetCloseHandle(hConnect);	return dwStatusCode == HTTP_STATUS_OK;}

BHOはCOMサーバーであるため、DllRegisterServerではCOMサーバーとしての情報をレジストリに書き込んでいます。これに加えてBHOの情報を書き込まなければならないため、次のキーを参照しています。

HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows\CurrentVersion\explorer\Browser Helper Objects

このキーのサブキーとして、オブジェクトのCLSIDを持ったキーを作成するようにします。これにより、BHOがIEにロードされることになります。既定ではBHOはエクスプローラーにもロードされますが、 NoExplorerというエントリを作成して1を指定すれば、ロードされないようになります。

DLLを作成したら、コマンドプロント上で次の文字列を入力します。ファイルパスの部分は、BHOが存在するパスに置き換えてください。

regsvr32 C:\sample.dll (登録の解除時は regsvr32 /u C:\sample.dll のようにする)

regsvr32にDLLのパスを指定すれば、DLLのDllRegisterServerを呼び出してくれます。これによってBHOの情報がレジストリに登録されることになり、 IEの起動時にBHOがロードされることになります。

本站仅提供存储服务,所有内容均由用户发布,如发现有害或侵权内容,请点击举报
打开APP,阅读全文并永久保存 查看更多类似文章
猜你喜欢
类似文章
【热】打开小程序,算一算2024你的财运
用纯粹的C++编写COM组件
COM编程技术基础之四
Writing a shell extension in plain C++
COM调用过程
COM——复合文档与持续化--YXM的程序人生
<font style="vertical-align: inherit;"><font style="vertical-align: inherit;">创建COM组件全过程(C ++)</font></font>
更多类似文章 >>
生活服务
热点新闻
分享 收藏 导长图 关注 下载文章
绑定账号成功
后续可登录账号畅享VIP特权!
如果VIP功能使用有故障,
可点击这里联系客服!

联系客服