編寫在瀏覽器中不彈出警告的ActiveX控件

我們在編寫ActiveX控件時,如果用在瀏覽器中,經常都會彈出現在運行的腳本不安全的提示, 如果給客戶使用,將會帶來極大不便。按照MSDN的介紹通常有兩種一種是實現IObjectSafe接口,一種是通過修改註冊表的方法。一般如果用ATL開發ActiveX控件,就用實現ObjectSafe接口的方法。如果用MFC開發,我覺得還是用修改註冊表的方法比較方便。下面我們將第二種方法:

要包括兩個文件

#include "comcat.h"
#include "Objsafe.h"

// 本控件的CLSID,註冊表用

const GUID CDECL CLSID_SafeItem =
		{ 0x7AE7497B, 0xCAD8, 0x4E66, { 0xA5,0x8B,0xDD,0xE9,0xBC,0xAF,0x6B,0x61 } };

// 創建組件種類

HRESULT CreateComponentCategory(CATID catid, WCHAR* catDescription)
{
    ICatRegister* pcr = NULL ;
    HRESULT hr = S_OK ;

    hr = CoCreateInstance(CLSID_StdComponentCategoriesMgr, 
            NULL, CLSCTX_INPROC_SERVER, IID_ICatRegister, (void**)&pcr);
    if (FAILED(hr))
        return hr;

    // Make sure the HKCR/Component Categories/{..catid...}
    // key is registered.
    CATEGORYINFO catinfo;
    catinfo.catid = catid;
    catinfo.lcid = 0x0409 ; // english

    // Make sure the provided description is not too long.
    // Only copy the first 127 characters if it is.
    int len = wcslen(catDescription);
    if (len>127)
        len = 127;
    wcsncpy(catinfo.szDescription, catDescription, len);
    // Make sure the description is null terminated.
    catinfo.szDescription[len] = ''/0'';

    hr = pcr->RegisterCategories(1, &catinfo);
        pcr->Release();

    return hr;
}

// 註冊組件種類

HRESULT RegisterCLSIDInCategory(REFCLSID clsid, CATID catid)
{
    // Register your component categories information.
    ICatRegister* pcr = NULL ;
    HRESULT hr = S_OK ;
    hr = CoCreateInstance(CLSID_StdComponentCategoriesMgr, 
                NULL, CLSCTX_INPROC_SERVER, IID_ICatRegister, (void**)&pcr);
    if (SUCCEEDED(hr))
    {
       // Register this category as being "implemented" by the class.
       CATID rgcatid[1] ;
       rgcatid[0] = catid;
       hr = pcr->RegisterClassImplCategories(clsid, 1, rgcatid);
    }
    if (pcr != NULL)
        pcr->Release();
    return hr;
}

// 卸載組件種類

HRESULT UnRegisterCLSIDInCategory(REFCLSID clsid, CATID catid)
{
    ICatRegister* pcr = NULL ;
    HRESULT hr = S_OK ;

    hr = CoCreateInstance(CLSID_StdComponentCategoriesMgr, 
            NULL, CLSCTX_INPROC_SERVER, IID_ICatRegister, (void**)&pcr);
    if (SUCCEEDED(hr))
    {
       // Unregister this category as being "implemented" by the class.
       CATID rgcatid[1] ;
       rgcatid[0] = catid;
       hr = pcr->UnRegisterClassImplCategories(clsid, 1, rgcatid);
    }

    if (pcr != NULL)
        pcr->Release();

    return hr;
}

// DllRegisterServer - Adds entries to the system registry

STDAPI DllRegisterServer(void)
{
	HRESULT hr;

	AFX_MANAGE_STATE(_afxModuleAddrThis);

	if (!AfxOleRegisterTypeLib(AfxGetInstanceHandle(), _tlid))
		return ResultFromScode(SELFREG_E_TYPELIB);

	if (!COleObjectFactoryEx::UpdateRegistryAll(TRUE))
		return ResultFromScode(SELFREG_E_CLASS);

    // 標記控件初始化安全.
    // 創建初始化安全組件種類
    hr = CreateComponentCategory(CATID_SafeForInitializing, L"Controls safely initializable from persistent data!");
    if (FAILED(hr))
        return hr;
    // 註冊初始化安全
    hr = RegisterCLSIDInCategory(CLSID_SafeItem, CATID_SafeForInitializing);
    if (FAILED(hr))
        return hr;

    // 標記控件腳本安全
    // 創建腳本安全組件種類 
    hr = CreateComponentCategory(CATID_SafeForScripting, L"Controls safely scriptable!");
    if (FAILED(hr))
        return hr;
    // 註冊腳本安全組件種類
    hr = RegisterCLSIDInCategory(CLSID_SafeItem, CATID_SafeForScripting);
    if (FAILED(hr))
        return hr;

	return NOERROR;
}

// DllUnregisterServer - Removes entries from the system registry

STDAPI DllUnregisterServer(void)
{
	HRESULT hr;

	AFX_MANAGE_STATE(_afxModuleAddrThis);

	if (!AfxOleUnregisterTypeLib(_tlid, _wVerMajor, _wVerMinor))
		return ResultFromScode(SELFREG_E_TYPELIB);

	if (!COleObjectFactoryEx::UpdateRegistryAll(FALSE))
		return ResultFromScode(SELFREG_E_CLASS);

    // 刪除控件初始化安全入口.
    hr=UnRegisterCLSIDInCategory(CLSID_SafeItem, CATID_SafeForInitializing);
    if (FAILED(hr))
        return hr;
    // 刪除控件腳本安全入口
    hr=UnRegisterCLSIDInCategory(CLSID_SafeItem, CATID_SafeForScripting);
    if (FAILED(hr))
        return hr;

//////////////////////////
	return NOERROR;
}


(全文完)

 

如果在本地使用ocx,那麼需要人工註冊,這種情況下您自己完全可以控制ocx的安全,如果想用,那麼您就認爲他是安全的了。

如果在internet上用,則一定要數字簽名,所以控件的安全由數字簽名來保證! ( rainsoft 發表於 2003-7-2 16:49:00)
 
如果說實現了這個接口就不會出提示,那麼不是想做什麼都可以,可以隨意控制客戶端的機器?邏輯上是可能的嗎? ( zerochang 發表於 2003-7-1 11:31:00)
 
這個好像不好用呀。沒有註冊過的機器不行。我試了。
那位可以的可以給我個例子嗎?[email protected]
我再想如果,真的可以隱式下載,那WIN系統豈不是很不安全了嗎?如何去控制惡意代碼?暈!!! ( lrcstar 發表於 2003-6-30 21:34:00)
 
希望樓主總結一下他們的觀點。 ( sander 發表於 2003-6-28 19:28:00)
 
不加入數字簽名,IE會禁止下載,
那樣只能夠保證下載後在本機執行時不彈出
警告。
實現IObjectSafet接口
添加到類別:
BEGIN_CATEGORY_MAP(Cctrl)
  IMPLEMENTED_CATEGORY(CATID_SafeForScripting)
  IMPLEMENTED_CATEGORY(CATID_SafeForInitializing)
END_CATEGORY_MAP() ( xwtwho 發表於 2003-6-27 14:11:00)
 
就話新說。。。。 ( zfive5 發表於 2003-6-27 13:06:00)
 
我在一本實例書上看見過,好象不買證書籤名還是不行的 ( peterlcm 發表於 2003-6-27 10:56:00)
 
控件下載前代碼不會被執行
需要在控件中實現IObjectSafety接口
在網上搜索一下就行了 ( 家寶 發表於 2003-6-27 10:44:00)
 
呵呵,偶前兩天爲這個問題困擾,才做過。方法一樣,不過我的註冊和卸載函數在BOOL CGraphView2ZTCtrl::CGraphView2ZTCtrlFactory::UpdateRegistry(BOOL bRegister)裏面添加的,效果一樣,不會有安全提示,^_^ ( warmchang 發表於 2003-6-27 9:32:00)

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章