スクリプトおよび初期化を実行しても安全として MFC コントロールにマークする方法


概要


デフォルトでは、MFC ActiveX コントロールは、スクリプトおよび初期化を実行しても安全としてマークされていません。これは、セキュリティ レベルが中または高に設定された Internet Explorer でコントロールを実行すると明らかになります。これらのモードでは、コントロールのデータが安全でないか、スクリプトの使用が安全でない可能性があることを示す警告が表示されます。


コントロールでこれらのエラーの発生を防止するには、次の 2 つの方法があります。最初の方法は、IObjectSafety インターフェイスを実装するコントロールに関する方法で、インターネット ブラウザのコンテキストで実行される際に動作を変更し、"安全" になるコントロールに対して有効です。2 番目の方法は、コントロールの DllRegisterServer 関数を変更し、レジストリでコントロールを "安全" であるとしてマークする方法です。この資料では 2 番目の方法について説明します。IObjectSafety インターフェイスを実装する最初の方法については、『Internet Client SDK』の説明を参照してください。


コントロールが実際に安全である場合のみ、安全としてマークする必要があることに注意してください。この説明については、『Internet Client SDK』のドキュメントで、「Component Development」の「Safe Initialization and Scripting for ActiveX Controls」を参照してください。


: この資料では、ダウンロードを実行しても安全としてマークする方法については説明していません。コードのダウンロードとコード署名の詳細については、『Internet Client SDK』を参照してください。

詳細


スクリプトおよび初期化を実行しても安全として MFC ActiveX コントロールにマークするには、以下の手順を実行します。
  1. 以下の cathelp.h および cathelp.cpp ファイルをプロジェクトに追加して、ヘルパ関数 CreateComponentCategory および RegisterCLSIDInCategory を実装します。

    Cathelp.h

          #include "comcat.h"

    // Helper function to create a component category and associated
    // description
    HRESULT CreateComponentCategory(CATID catid, WCHAR* catDescription);

    // Helper function to register a CLSID as belonging to a component
    // category
    HRESULT RegisterCLSIDInCategory(REFCLSID clsid, CATID catid);

    Cathelp.cpp

          #include "comcat.h"

    // Helper function to create a component category and associated
    // description
    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;
    }

    // Helper function to register a CLSID as belonging to a component
    // category
    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;
    }
  2. DllRegisterServer を変更し、コントロールを安全としてマークします。プロジェクトの .cpp ファイルに DllRegisterServer の実装を配置します。この .cpp ファイルにはいくつかの要素を追加する必要があります。CreateComponentCategory および RegisterCLSIDInCategory を実装するファイルをインクルードします。

          #include "CatHelp.h"
    安全なコンポーネント カテゴリに関連付けられた GUID を定義します。
          const CATID CATID_SafeForScripting     =
    {0x7dd95801,0x9882,0x11cf,{0x9f,0xa9,0x00,0xaa,0x00,0x6c,0x42,0xc4}};
    const CATID CATID_SafeForInitializing =
    {0x7dd95802,0x9882,0x11cf,{0x9f,0xa9,0x00,0xaa,0x00,0x6c,0x42,0xc4}};
    コントロールに関連付けられた GUID を定義します。コントロールのメインの .cpp ファイルにある IMPLEMENT_OLECREATE_EX マクロから GUID を参照すると、容易に定義できます。以下のような形式に修正します。
          const GUID CDECL BASED_CODE _ctlid =
    { 0x43bd9e45, 0x328f, 0x11d0,
    { 0xa6, 0xb9, 0x0, 0xaa, 0x0, 0xa7, 0xf, 0xc2 } };
    スクリプトと初期化の両方を実行しても安全としてコントロールにマークするには、DllRegisterServer 関数を以下のように変更します。
          STDAPI DllRegisterServer(void)
    {
    AFX_MANAGE_STATE(_afxModuleAddrThis);

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

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

    if (FAILED( CreateComponentCategory(
    CATID_SafeForScripting,
    L"Controls that are safely scriptable") ))
    return ResultFromScode(SELFREG_E_CLASS);

    if (FAILED( CreateComponentCategory(
    CATID_SafeForInitializing,
    L"Controls safely initializable from persistent data") ))
    return ResultFromScode(SELFREG_E_CLASS);

    if (FAILED( RegisterCLSIDInCategory(
    _ctlid, CATID_SafeForScripting) ))
    return ResultFromScode(SELFREG_E_CLASS);

    if (FAILED( RegisterCLSIDInCategory(
    _ctlid, CATID_SafeForInitializing) ))
    return ResultFromScode(SELFREG_E_CLASS);

    return NOERROR;
    }
以下に示す 2 つの理由により、通常は DllUnregisterServer 関数は変更しません。
  • 他のコントロールがコンポーネント カテゴリを使用している可能性があるため、コンポーネント カテゴリは削除しない。
  • UnRegisterCLSIDInCategory 関数が定義されてるが、デフォルトでは DllUnregisterServer によってコントロールのエントリがレジストリからすべて削除されるため、コントロールの登録情報からカテゴリを削除しても、ほとんど意味がない。
コントロールのコンパイルと登録が完了すると、レジストリに以下のエントリが登録されていることがわかります。


HKEY_CLASSES_ROOT\Component
Categories\{7DD95801-9882-11CF-9FA9-00AA006C42C4}

HKEY_CLASSES_ROOT\Component
Categories\{7DD95802-9882-11CF-9FA9-00AA006C42C4}

HKEY_CLASSES_ROOT\CLSID\{"your controls GUID"}\Implemented
Categories\{7DD95801-9882-11CF-9FA9-00AA006C42C4}

HKEY_CLASSES_ROOT\CLSID\{"your controls GUID"}\Implemented
Categories\{7DD95802-9882-11CF-9FA9-00AA006C42C4}

関連情報


Internet Client SDK - Component Development - Safe Initialization and Scripting for ActiveX Controls