今回は ActiveX に 安全であること を示す実装を行うことで、IEの 警告表示 を回避してみる。
ちなみに、実装は C# (自分が分かる範囲だからという軽い理由…)。
自分が知る限り、ActiveX の 警告回避 は以下のどれかでなかろうかと…思ってる。
そのうち、今回は「ActiveX に安全マークをつける」方法のうち、「コード上に実装する」方法。
- ActiveXにデジタル署名する
- 一般的な認証局で発行したデジタル署名を利用
- オレオレ認証局で発行したデジタル署名を利用
- ActiveXを登録時に安全マークをつける
- コード上に実装する
- レジストリに"事前承認済み"書き込む(→詳細)
- レジストリに"安全マーク"書き込む(→詳細)
さて、前置きが長くなりましたが…これから実装を始めます。
実装はいたって単純で、 「IObjectSafety インターフェース」と「IObjectSafety 実装」をコピペして、「IObjectSafety 実装」を継承するだけ。
さて、その「IObjectSafety インターフェース」と「IObjectSafety 実装」についてを以下に載せます。
IObjectSafety.cs
namespace Sample.ActiveXPlugIn
{
using System;
using System.Collections.Generic;
using System.Linq;
using System.Runtime.InteropServices;
using System.Text;
[ComImport, Guid("CB5BDC81-93C1-11CF-8F20-00805F2CD064")]
[InterfaceType(ComInterfaceType.InterfaceIsIUnknown)]
public interface IObjectSafety
{
[PreserveSig]
uint GetInterfaceSafetyOptions(
ref Guid riid,
[MarshalAs(UnmanagedType.U4)] ref int pdwSupportedOptions,
[MarshalAs(UnmanagedType.U4)] ref int pdwEnabledOptions);
[PreserveSig]
uint SetInterfaceSafetyOptions(
ref Guid riid,
[MarshalAs(UnmanagedType.U4)] int dwOptionSetMask,
[MarshalAs(UnmanagedType.U4)] int dwEnabledOptions);
}
}
COM 関係が利用したいので、System.Runtime.InteropServices 名前空間を追加します。
属性をいくつか付けるのですが、COM の実装に合わせるため、GUID "CB5BDC81-93C1-11CF-8F20-00805F2CD064" も含めて、
まったく同じ属性をつけます。
…というか、"CB5BDC81-93C1-11CF-8F20-00805F2CD064" が安全マークを示すインターフェースの実態のようです。
IObjectSafetyTLB.cs
namespace Sample.ActiveXPlugIn
{
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
public class IObjectSafetyTLB : IObjectSafety
{
// ---------------------------------------------------
// 定数
// ---------------------------------------------------
private const int INTERFACESAFE_FOR_UNTRUSTED_CALLER = 0x00000001;
private const int INTERFACESAFE_FOR_UNTRUSTED_DATA = 0x00000002;
private const int INTERFACE_USES_DISPEX = 0x00000004;
private const int INTERFACE_USES_SECURITY_MANAGER = 0x00000008;
private const uint S_OK = 0x00000000;
private const uint E_NOINTERFACE = 0x80004002;
private const uint E_FAIL = 0x80004005;
// ---------------------------------------------------
// メンバ関数
// ---------------------------------------------------
public uint GetInterfaceSafetyOptions(ref Guid riid, ref int pdwSupportedOptions, ref int pdwEnabledOptions)
{
return S_OK;
}
public uint SetInterfaceSafetyOptions(ref Guid riid, int dwOptionSetMask, int dwEnabledOptions)
{
return S_OK;
}
}
}
IObjectSafety インターフェースを実装する実態クラスになります。
本来は、引き渡された参照データ(pdwSupportedOptions, pdwEnabledOptionsとか…)を参考にイロイロこねくり回して、
S_OK, E_NOINTERFACE, E_FAIL のどれかを返すようです。
が、面倒くさいのとよく分からないとを理由に無条件に S_OK として使わせてもらいます。
ちなみに、その他の定数周りはインターネットから拾ってきたので、怪しいです…。。
あとは、IObjectSafetyTLB クラス を plugin にしたいクラスに対して継承させてあげればOK。
IObjextSafetyTLB を継承した サンプルコード
namespace Sample.ActiveXPlugIn
{
using System;
using System.Collections.Generic;
using System.Linq;
using System.Runtime.InteropServices;
using System.Text;
using System.Windows.Forms;
[Guid("YOURGUID-0000-0000-0000-000000000000")]
[ComSourceInterfaces(typeof(IMyFormEvent))]
[ClassInterface(ClassInterfaceType.None)]
[ProgId("Sample.ActiveXPlugIn.MyForm")]
public class MyForm : IObjectSafetyTLB, IMyFormMethod
{
// IE プラグイン の実装。
}
}
さすがにとは思いますが…
プラグインのGUID"YOURGUID-0000-0000-0000-000000000000"や名前空間"Sample.ActiveXPlugIn"、
プラグイン実態クラス名"MyForm"、プラグインインターフェース名"IMyFormEvent", "IMyFormMethod" などは任意に読み替え、書き換えてください。
今回、参考にさせていただいた情報源は以下の通りです。