Hi all,
i´m using a custom download manager for years now.
Until now i integrated it into ie modifying ie´s
contextmenu. Clicking "my downlod" here fires a script
that passes the url of the file to download and the
url of the current site to my download manger. Works
very well alltogether.
Since pb offers writing com dll now, i wanted to invoke my
download manger by a left click with the mouse instead of
right click (-> contextmenu), left click (-> my download).
There are two ways to do it (as far as i know until now).
1.) writing a BHO (Browser Helper Object) for ie
2.) writing a custom download manger intergating into ie
below is some c code i put together from snippets i found on the web
it compiles and after registering it works as expected !
From that i tried to port it to pb for a start i use the code below
it copiles, can be registerd, the dll loads into ie
(msgbox "BHO works !" appears when starting ie) but
dosent integrate into ie (no msgbox "SetSite").
As fas i understand, my bho must expose a "IObjectWithSite"
interface with two methods: "SetSite" and "GetSite".
SetSite method should be called by ie upon loading a new site.
Nothing happens.
All registry settings seem to be correct, otherwise "BHO works !"
shouldn´t appear. The dll stays loaded into ie, while it is running
("BHO end" appears if ie is closed). i embedded the typelib into my
dll, pb com browser shows my class as expected.
Oleview shows IObjectWithSite interface is marked as noncreatable ???
Letters are all uppercase (IOBJECTWITHSITE) does this matter,
because c is case sensitive, is com case sensitive too ?
So what am i doing wrong here ? Help appreciated.
c code sample:
#################################################
pb code:
'***********************************************************************************************
'***********************************************************************************************
this what i get from com browser:
' Generated by: PowerBASIC COM Browser v.2.00.0058
' DateTime : 08.11.2008 at 13:26
' ------------------------------------------------
' Library Name: BHO_dll
' Library File: C:\Programme\PBDLL60\IDE\Projects\ie-extension\bho.dll
' Description : BHO Testversion
' GUID : {8C5D6B75-6CC0-4116-A720-55E17E190C78}
' LCID : 0
' Version : 1.0
' Version Dependant ProgID's
$PROGID_BHO_dll_BHOCLASS = "BHOCLASS"
' Class Indentifiers
$CLSID_BHO_dll_BHOCLASS = GUID$("{AFB0FFF8-5266-4B84-A97B-C1AE763D0788}")
' Interface Indentifiers
$IID_BHO_dll_IOBJECTWITHSITE = GUID$("{2D240C73-EF92-493E-8543-DD2BE1073523}")
' Interface Name : IOBJECTWITHSITE
' Description : IOBJECTWITHSITE is a dual interface with IDispatch.
' ClassID : $CLSID_BHO_dll_BHOCLASS
Interface IOBJECTWITHSITE $IID_BHO_dll_IOBJECTWITHSITE
Inherit IDispatch
Method SETSITE <257> (Byval PARAM1 As DWord) As DWord
Method GETSITE <258> (Byval PARAM1 As DWord, ByRef In PARAM2 As DWord) As DWord
End Interface
this is what oleview shows:
// Generated .IDL file (by the OLE/COM Object Viewer)
//
// typelib filename: bho.dll
[
uuid(8C5D6B75-6CC0-4116-A720-55E17E190C78),
version(1.0),
helpstring("BHO Testversion")
]
library BHO_dll
{
// TLib : // TLib : OLE Automation : {00020430-0000-0000-C000-000000000046}
importlib("stdole32.tlb");
// Forward declare all types defined in this typelib
interface IOBJECTWITHSITE;
[
odl,
uuid(2D240C73-EF92-493E-8543-DD2BE1073523),
helpstring("IOBJECTWITHSITE is a dual interface with IDispatch."),
dual,
nonextensible,
oleautomation
]
interface IOBJECTWITHSITE : IDispatch {
[id(0x00000101)]
HRESULT SETSITE(
[in] unsigned long PARAM1,
[out, retval] unsigned long* );
[id(0x00000102)]
HRESULT GETSITE(
[in] unsigned long PARAM1,
[in, out] unsigned long* PARAM2,
[out, retval] unsigned long* );
};
[
uuid(AFB0FFF8-5266-4B84-A97B-C1AE763D0788),
noncreatable
]
coclass BHOCLASS {
[default] interface IOBJECTWITHSITE;
};
};
i´m using a custom download manager for years now.
Until now i integrated it into ie modifying ie´s
contextmenu. Clicking "my downlod" here fires a script
that passes the url of the file to download and the
url of the current site to my download manger. Works
very well alltogether.
Since pb offers writing com dll now, i wanted to invoke my
download manger by a left click with the mouse instead of
right click (-> contextmenu), left click (-> my download).
There are two ways to do it (as far as i know until now).
1.) writing a BHO (Browser Helper Object) for ie
2.) writing a custom download manger intergating into ie
below is some c code i put together from snippets i found on the web
it compiles and after registering it works as expected !
From that i tried to port it to pb for a start i use the code below
it copiles, can be registerd, the dll loads into ie
(msgbox "BHO works !" appears when starting ie) but
dosent integrate into ie (no msgbox "SetSite").
As fas i understand, my bho must expose a "IObjectWithSite"
interface with two methods: "SetSite" and "GetSite".
SetSite method should be called by ie upon loading a new site.
Nothing happens.
All registry settings seem to be correct, otherwise "BHO works !"
shouldn´t appear. The dll stays loaded into ie, while it is running
("BHO end" appears if ie is closed). i embedded the typelib into my
dll, pb com browser shows my class as expected.
Oleview shows IObjectWithSite interface is marked as noncreatable ???
Letters are all uppercase (IOBJECTWITHSITE) does this matter,
because c is case sensitive, is com case sensitive too ?
So what am i doing wrong here ? Help appreciated.
c code sample:
Code:
#include <windows.h> #include <tchar.h> #include <exdisp.h> #include <exdispid.h> #include <mshtml.h> #include <mshtmdid.h> #include <shlwapi.h> HINSTANCE hInstance; LONG gref=0; const CLSID BhoCLSID = {0xC9C42510,0x9B41,0x42c1,0x9D,0xCD,0x72,0x82,0xA2,0xD0,0x7C,0x61}; #define BhoCLSIDs _T("{C9C42510-9B41-42c1-9DCD-7282A2D07C61}") class BHO : public IObjectWithSite, public IDispatch { long ref; IWebBrowser2* webBrowser; IHTMLDocument* doc; IHTMLDocument2 *doc2; IHTMLWindow2 *win2; public: // IUnknown... HRESULT STDMETHODCALLTYPE QueryInterface(REFIID riid, void **ppv) { if (riid==IID_IUnknown) *ppv=static_cast<BHO*>(this); else if (riid==IID_IObjectWithSite) *ppv=static_cast<IObjectWithSite*>(this); else if (riid==IID_IDispatch) *ppv=static_cast<IDispatch*>(this); else return E_NOINTERFACE; AddRef(); return S_OK;} ULONG STDMETHODCALLTYPE AddRef() { InterlockedIncrement(&gref); return InterlockedIncrement(&ref);} ULONG STDMETHODCALLTYPE Release() { int tmp=InterlockedDecrement(&ref); if (tmp==0) delete this; InterlockedDecrement(&gref); return tmp;} // IDispatch... HRESULT STDMETHODCALLTYPE GetTypeInfoCount(unsigned int FAR* pctinfo) { *pctinfo=1; return NOERROR;} HRESULT STDMETHODCALLTYPE GetTypeInfo(unsigned int iTInfo, LCID lcid, ITypeInfo FAR* FAR* ppTInfo) { return NOERROR;} HRESULT STDMETHODCALLTYPE GetIDsOfNames(REFIID riid, OLECHAR FAR* FAR* rgszNames, unsigned int cNames, LCID lcid, DISPID FAR* rgDispId) { return NOERROR;} HRESULT STDMETHODCALLTYPE Invoke(DISPID dispIdMember, REFIID riid, LCID lcid, WORD wFlags, DISPPARAMS FAR* pDispParams, VARIANT FAR* pVarResult, EXCEPINFO FAR* pExcepInfo, unsigned int FAR* puArgErr) { // DISPID_DOCUMENTCOMPLETE: This is the earliest point we can obtain the "document" interface if (dispIdMember==DISPID_DOCUMENTCOMPLETE) { if (!webBrowser) return E_FAIL; IDispatch *idisp; webBrowser->get_Document(&idisp); if (idisp && !doc) idisp->QueryInterface(IID_IHTMLDocument, (void**)&doc); if (idisp && !doc2) idisp->QueryInterface(IID_IHTMLDocument2, (void**)&doc2); if (doc2 && !win2) doc2->get_parentWindow(&win2); IConnectionPointContainer *cpc=0; if (doc) doc->QueryInterface(IID_IConnectionPointContainer, (void**) &cpc); IConnectionPoint* cp=0; if (cpc) cpc->FindConnectionPoint(DIID_HTMLDocumentEvents2, &cp); DWORD cookie; HRESULT hr; if (cp) hr=cp->Advise(static_cast<IDispatch*>(this), &cookie); if (cp) cp->Release(); if (cpc) cpc->Release(); if (idisp) idisp->Release(); if (!doc || !doc2 || !win2 || hr!=S_OK) {release(); return E_FAIL;} return NOERROR; } if (dispIdMember==DISPID_HTMLDOCUMENTEVENTS_ONCLICK) { // This shows how to respond to simple events. MessageBox(0,_T("Try pressing some keys on the keyboard!"),_T("BHO"),MB_OK); return NOERROR; } if (dispIdMember==DISPID_HTMLDOCUMENTEVENTS_ONKEYDOWN) { // This shows how to examine the "event object" of an event IDispatch *param1=0; if (pDispParams->cArgs==1 && (pDispParams->rgvarg)[0].vt==VT_DISPATCH) param1=(pDispParams->rgvarg)[0].pdispVal; IHTMLEventObj *pEvtObj=0; if (param1) param1->QueryInterface(IID_IHTMLEventObj, (void**)&pEvtObj); long keycode; HRESULT hr; if (pEvtObj) hr=pEvtObj->get_keyCode(&keycode); if (pEvtObj) pEvtObj->Release(); if (!pEvtObj || hr!=S_OK) return E_FAIL; // This shows how to manipulate the CSS style of an element int i=keycode-32; if (i<0) i=0; if (i>63) i=63; i*=4; wchar_t buf[100]; wsprintfW(buf,L"rgb(%i,%i,%i)",i,255-i,i/2); IHTMLElement *body=0; doc2->get_body(&body); IHTMLStyle *style=0; if (body) body->get_style(&style); VARIANT v; v.vt=VT_BSTR; v.bstrVal=buf; if (style) style->put_backgroundColor(v); if (style) style->Release(); if (body) body->Release(); if (!body || !style) return E_FAIL; return NOERROR; } return NOERROR; } // IObjectWithSite... HRESULT STDMETHODCALLTYPE GetSite(REFIID riid, void** ppvSite) { return E_NOINTERFACE;} HRESULT STDMETHODCALLTYPE SetSite(IUnknown* iunk) { // This is called by IE to plug us into the current web window release(); iunk->QueryInterface(IID_IWebBrowser2, (void**)&webBrowser); IConnectionPointContainer *cpc=0; iunk->QueryInterface(IID_IConnectionPointContainer, (void**)&cpc); IConnectionPoint* cp=0; if (cpc) cpc->FindConnectionPoint(DIID_DWebBrowserEvents2, &cp); DWORD cookie; HRESULT hr; if (cp) hr=cp->Advise(static_cast<IDispatch*>(this), &cookie); if (!webBrowser || !cpc || !cp || hr!=S_OK) {if (cp) cp->Release(); if (cpc) cpc->Release(); release(); return E_FAIL;} return S_OK; } // BHO... BHO() : ref(0), webBrowser(0), doc(0), doc2(0), win2(0) {}; ~BHO() {release();} void release() { if (webBrowser) webBrowser->Release(); webBrowser=0; if (doc) doc->Release(); doc=0; if (doc2) doc2->Release(); doc2=0; if (win2) win2->Release(); win2=0;} }; class MyClassFactory : public IClassFactory { long ref; public: // IUnknown... (nb. this class is instantiated statically, which is why Release() doesn't delete it.) HRESULT STDMETHODCALLTYPE QueryInterface(REFIID riid, void **ppv) { if (riid==IID_IUnknown || riid==IID_IClassFactory) {*ppv=this; AddRef(); return S_OK;} else return E_NOINTERFACE;} ULONG STDMETHODCALLTYPE AddRef() { InterlockedIncrement(&gref); return InterlockedIncrement(&ref);} ULONG STDMETHODCALLTYPE Release() { int tmp = InterlockedDecrement(&ref); InterlockedDecrement(&gref); return tmp;} // IClassFactory... HRESULT STDMETHODCALLTYPE LockServer(BOOL b) { if (b) InterlockedIncrement(&gref); else InterlockedDecrement(&gref); return S_OK;} HRESULT STDMETHODCALLTYPE CreateInstance(LPUNKNOWN pUnkOuter, REFIID riid, LPVOID *ppvObj) { *ppvObj = NULL; if (pUnkOuter) return CLASS_E_NOAGGREGATION; BHO *bho=new BHO(); bho->AddRef(); HRESULT hr=bho->QueryInterface(riid, ppvObj); bho->Release(); return hr;} // MyClassFactory... MyClassFactory() : ref(0) {} }; STDAPI DllGetClassObject(REFCLSID rclsid, REFIID riid, LPVOID *ppvOut) { static MyClassFactory factory; *ppvOut = NULL; if (rclsid==BhoCLSID) {return factory.QueryInterface(riid,ppvOut);} else return CLASS_E_CLASSNOTAVAILABLE; } STDAPI DllCanUnloadNow(void) { return (gref>0)?S_FALSE:S_OK; } STDAPI DllRegisterServer(void) { TCHAR fn[MAX_PATH]; GetModuleFileName(hInstance,fn,MAX_PATH); SHSetValue(HKEY_CLASSES_ROOT,_T("CLSID\\")BhoCLSIDs,_T(""),REG_SZ,_T("BHO"),4*sizeof(TCHAR)); SHSetValue(HKEY_CLASSES_ROOT,_T("CLSID\\")BhoCLSIDs _T("\\InProcServer32"),_T(""),REG_SZ,fn,((int)_tcslen(fn)+1)*sizeof(TCHAR)); SHSetValue(HKEY_CLASSES_ROOT,_T("CLSID\\")BhoCLSIDs _T("\\InProcServer32"),_T("ThreadingModel"),REG_SZ,_T("Apartment"),10*sizeof(TCHAR)); SHSetValue(HKEY_LOCAL_MACHINE,_T("SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Explorer\\Browser Helper Objects\\")BhoCLSIDs,_T(""),REG_SZ,_T(""),sizeof(TCHAR)); return S_OK; } STDAPI DllUnregisterServer() { SHDeleteKey(HKEY_CLASSES_ROOT,_T("CLSID\\") BhoCLSIDs); SHDeleteKey(HKEY_LOCAL_MACHINE,_T("SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Explorer\\Browser Helper Objects\\")BhoCLSIDs); return S_OK; } BOOL WINAPI DllMain(HINSTANCE hinstDLL, DWORD fdwReason, LPVOID lpvReserved) { if (fdwReason==DLL_PROCESS_ATTACH) hInstance=hinstDLL; TCHAR szFilename[MAX_PATH]; GetModuleFileName(NULL, szFilename, MAX_PATH); _tcslwr(szFilename); if (_tcsstr(szFilename, _T("explorer.exe")) != NULL) return FALSE; // For performance reasons, we don't want to be called on thread events DisableThreadLibraryCalls(hinstDLL); return TRUE; }
pb code:
Code:
#COMPILE DLL "BHO.dll" #DIM ALL #COM DOC "BHO Testversion" #COM NAME "BHO_dll", 1.0 #COM GUID GUID$("{8C5D6B75-6CC0-4116-A720-55E17E190C78}") #COM TLIB ON #RESOURCE "BHO.pbr" %USEMACROS = 1 #INCLUDE "Win32API.inc" '*********************************************************************************************** '*********************************************************************************************** FUNCTION LIBMAIN (BYVAL hInstance AS LONG, _ BYVAL fwdReason AS LONG, _ BYVAL lpvReserved AS LONG) AS LONG '*********************************************************************************************** ' Main DLL entry point called by Windows... '*********************************************************************************************** LOCAL szfilename AS ASCIIZ * %MAX_Path SELECT CASE fwdReason CASE %DLL_PROCESS_ATTACH hInst = hInstance GetModuleFileName(BYVAL 0, szFilename, %MAX_PATH) IF INSTR(LCASE$(szfilename), "iexplore.exe")<>0 THEN MSGBOX "BHO works !" FUNCTION=1 ELSE FUNCTION=1'0 'must be 1 for regsvr32, otherwise 0 to prevent from attching to explorer END IF CASE %DLL_PROCESS_DETACH MSGBOX "BHO end" FUNCTION = 1 'success! CASE %DLL_THREAD_ATTACH FUNCTION = 1 'success! CASE %DLL_THREAD_DETACH FUNCTION = 1 'success! END SELECT END FUNCTION '********************************************************************************************** ' IObjectWithSite : SetSite method '*********************************************************************************************** $BHOclassGuid = GUID$("{AFB0FFF8-5266-4B84-A97B-C1AE763D0788}") $BHOinterfaceGuid = GUID$("{2D240C73-EF92-493E-8543-DD2BE1073523}") CLASS BHOclass $BHOclassGuid AS COM INTERFACE IObjectWithSite $BHOinterfaceGuid : INHERIT DUAL ' INTERFACE IObjectWithSite $BHOinterfaceGuid : INHERIT Iunknown METHOD SetSite (BYVAL Param1 AS DWORD) AS DWORD MSGBOX "SetSite" END METHOD METHOD GetSite (BYVAL param1 AS DWORD, param2 AS DWORD) AS DWORD END METHOD END INTERFACE END CLASS
'***********************************************************************************************
'***********************************************************************************************
this what i get from com browser:
' Generated by: PowerBASIC COM Browser v.2.00.0058
' DateTime : 08.11.2008 at 13:26
' ------------------------------------------------
' Library Name: BHO_dll
' Library File: C:\Programme\PBDLL60\IDE\Projects\ie-extension\bho.dll
' Description : BHO Testversion
' GUID : {8C5D6B75-6CC0-4116-A720-55E17E190C78}
' LCID : 0
' Version : 1.0
' Version Dependant ProgID's
$PROGID_BHO_dll_BHOCLASS = "BHOCLASS"
' Class Indentifiers
$CLSID_BHO_dll_BHOCLASS = GUID$("{AFB0FFF8-5266-4B84-A97B-C1AE763D0788}")
' Interface Indentifiers
$IID_BHO_dll_IOBJECTWITHSITE = GUID$("{2D240C73-EF92-493E-8543-DD2BE1073523}")
' Interface Name : IOBJECTWITHSITE
' Description : IOBJECTWITHSITE is a dual interface with IDispatch.
' ClassID : $CLSID_BHO_dll_BHOCLASS
Interface IOBJECTWITHSITE $IID_BHO_dll_IOBJECTWITHSITE
Inherit IDispatch
Method SETSITE <257> (Byval PARAM1 As DWord) As DWord
Method GETSITE <258> (Byval PARAM1 As DWord, ByRef In PARAM2 As DWord) As DWord
End Interface
this is what oleview shows:
// Generated .IDL file (by the OLE/COM Object Viewer)
//
// typelib filename: bho.dll
[
uuid(8C5D6B75-6CC0-4116-A720-55E17E190C78),
version(1.0),
helpstring("BHO Testversion")
]
library BHO_dll
{
// TLib : // TLib : OLE Automation : {00020430-0000-0000-C000-000000000046}
importlib("stdole32.tlb");
// Forward declare all types defined in this typelib
interface IOBJECTWITHSITE;
[
odl,
uuid(2D240C73-EF92-493E-8543-DD2BE1073523),
helpstring("IOBJECTWITHSITE is a dual interface with IDispatch."),
dual,
nonextensible,
oleautomation
]
interface IOBJECTWITHSITE : IDispatch {
[id(0x00000101)]
HRESULT SETSITE(
[in] unsigned long PARAM1,
[out, retval] unsigned long* );
[id(0x00000102)]
HRESULT GETSITE(
[in] unsigned long PARAM1,
[in, out] unsigned long* PARAM2,
[out, retval] unsigned long* );
};
[
uuid(AFB0FFF8-5266-4B84-A97B-C1AE763D0788),
noncreatable
]
coclass BHOCLASS {
[default] interface IOBJECTWITHSITE;
};
};
Comment