構建一個安全的ActiveX控件

如果希望再IE載入控件的時候不對控件不安全作出警告的信息的話,你必須保證執行代碼使用安全的初始化和腳本的Active控件。相關的細節可以參照微軟MSDN上的文章“Safe Initialization and Scripting for ActiveX Controls”。本文的後面會給出鏈接地址。不過我在這篇文章裏面看到了大量的錯誤和冗長的文章。其實只需要在代碼中加入DllRegisterServer和DllUnregisterServer這兩個方法。下面我們就一步步指導你把ActiveX控件改成安全的:


編輯MyActiveX.cpp文件加入下面代碼。在你的ActiveX控件中CLSID_SafeItem的值需要等於你在MyActiveXCtrl.cpp文件中的IMPLEMENT_OLECREATE_EX,同時,這個值也要和你在網頁中的OBJECT ID標記CLSID值相同。

 #include "comcat.h"
 #include "strsafe.h"
 #include "objsafe.h"
  
 // CLSID_SafeItem - Necessary for safe ActiveX control
 // Id taken from IMPLEMENT_OLECREATE_EX function in xxxCtrl.cpp
  
 const CATID CLSID_SafeItem =
 { 0x36299202, 0x9ef, 0x4abf,{ 0xad, 0xb9, 0x47, 0xc5, 0x99, 0xdb, 0xe7, 0x78}};
 
 // HRESULT CreateComponentCategory - Used to register ActiveX control as safe 
  
 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
    size_t len;
    // Make sure the provided description is not too long.
    // Only copy the first 127 characters if it is.
    // The second parameter of StringCchLength is the maximum
    // number of characters that may be read into catDescription.
    // There must be room for a NULL-terminator. The third parameter
    // contains the number of characters excluding the NULL-terminator.
    hr = StringCchLength(catDescription, STRSAFE_MAX_CCH, &len);
    if (SUCCEEDED(hr))
        {
        if (len>127)
          {
            len = 127;
          }
        }   
    else
        {
          // TODO: Write an error handler;
        }
    // The second parameter of StringCchCopy is 128 because you need 
    // room for a NULL-terminator.
    hr = StringCchCopy(catinfo.szDescription, len + 1, catDescription);
    // Make sure the description is null terminated.
    catinfo.szDescription[len + 1] = '/0';
 
    hr = pcr->RegisterCategories(1, &catinfo);
    pcr->Release();
 
    return hr;
}
 
// HRESULT RegisterCLSIDInCategory -
//      Register your component categories information
 
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 - Remove entries from the registry
 
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方法:

STDAPI DllRegisterServer(void) {
    HRESULT hr;    // HResult used by Safety Functions
 
    AFX_MANAGE_STATE(_afxModuleAddrThis);
 
    if (!AfxOleRegisterTypeLib(AfxGetInstanceHandle(), _tlid))
      return ResultFromScode(SELFREG_E_TYPELIB);
 
    if (!COleObjectFactoryEx::UpdateRegistryAll(TRUE))
      return ResultFromScode(SELFREG_E_CLASS);
 
    // Mark the control as safe for initializing.
                                             
    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;
 
    // Mark the control as safe for scripting.
 
    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方法:

STDAPI DllUnregisterServer(void)
{
    HRESULT hr;    // HResult used by Safety Functions
 
    AFX_MANAGE_STATE(_afxModuleAddrThis);
 
    if (!AfxOleUnregisterTypeLib(_tlid, _wVerMajor, _wVerMinor))
      return ResultFromScode(SELFREG_E_TYPELIB);
 
    if (!COleObjectFactoryEx::UpdateRegistryAll(FALSE))
      return ResultFromScode(SELFREG_E_CLASS);
 
    // Remove entries from the registry.
 
    hr=UnRegisterCLSIDInCategory(CLSID_SafeItem, 
                     CATID_SafeForInitializing);
    if (FAILED(hr))
      return hr;
 
    hr=UnRegisterCLSIDInCategory(CLSID_SafeItem, 
                        CATID_SafeForScripting);
    if (FAILED(hr))
      return hr;
 
    return NOERROR;
}

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