COM から Request オブジェクトを利用する
MINI SERIES
今回の目的
ASP の組込みオブジェクトである Request オブジェクトを COM コンポーネントから直接参照してみたいと思います。なお対象者は、COM オブジェクトを作成したことがあるものとして話を進めてきます。
目的は、Request.ServerVariables の所有している IIS の環境変数を取得して何かをしようというものです。なお環境変数といっても、getenv 等を利用するだけでは、HTTP_REFERER のような HTTP ヘッダを取得することはできません。
今回は、IIS の環境変数を取得する一例として、単純に HTTP_USER_AGENT を取得するプロパティを持つコンポーネントを作成してみることにします。
ATL COM AppWizard
まず、Visual C++ 6.0 を起動したら、ATL COM AppWizard の新規作成を行います。
とりあえず、今回は HTTP というプロジェクト名にしてみます。また設定はディフォルトのままでかまいませんが、念のためサーバタイプが ”ダイナミックリンクライブラリ” であることを確認しておきましょう。
以上で設定は完了です。
【終了】 ボタンを押せば、ソースファイルが生成されます。
インターフェイスの作成
ASP の組込みオブジェクトを使用できるインターフェイスを作成します。
システムメニューの 【挿入】 → 【ATL オブジェクトの新規作成】 を選択します。すると作成するオブジェクトを選択するためのダイアログボックスが現れますので、”オブジェクト” カテゴリの ”ActiveX サーバーコンポーネント” を選択します。
すると作成するオブジェクトの情報を入力する画面が現れます。
ショートネームに、今回は Variables という名前を設定することにします。ショートネームに書き込むだけでこの部分すべてのエディットボックスにも自動的に値が挿入されます。
また Request オブジェクトを利用することも、この時点で設定しておく必要があります。
【ASP】 タブへ移動して、【固有のオブジェクト】 欄から利用したい ASP 固有のオブジェクトを選択します。今回の場合は Request オブジェクトなので、【要求】 にチェックを入れてください。
なお、固有のオブジェクトを使用するには、右側の OnStartPage/OnEndPage も使用する必要がありますのでそこにもチェックを入れておきましょう。
これでインターフェイスの作成は完了です。
コードの追加
まずは HTTP_USER_AGENT の値を返すためのプロパティを作成しましょう。
先ほど作成したインターフェイス IVariables に読取専用の BSTR プロパティ UserAgent を作成してください。
以下のようにプログラムを作成します。
ATL COM AppWizard が m_piRequest に自動的に ASP から Request オブジェクトを取り出せるようにプログラムを生成してくれるので、利用するのは比較的簡単です。
あとは、Request オブジェクトから ServerVariables 変数を抽出して、目的の環境変数名を使って値を取り出すという作業を行います。環境変数から取り出した値を BSTR 型に変換しないとうまくいかないので気をつけましょう。
Request オブジェクトから ServerVariables オブジェクトを取り出すには、Request.get_ServerVariables メソッドを使用します。その際、取り出された値を保存するために、IRequestDictionary のポインタを渡す必要があります。
ServerVariables オブジェクトの取得が完了したら、続いて RequestDirectory オブジェクトの get_Item メソッドを使用して環境変数の抽出を行います。このメソッドには、環境変数名と、実際の値を格納するための VARIANT 変数を2つ渡します。
そして取り出された環境変数の値が格納された VARIANT 変数を、VariantChangeType 関数を使用して BSTR 型へ変換します。
以上の点をプログラムでまとめるとこのようになります。
STDMETHODIMP CVariables::get_UserAgent(BSTR *pVal)
{
CComPtr<IRequestDictionary> m_piServerVariables;
// Request.ServerVariables オブジェクトのポインタを取得
if (SUCCEEDED(m_piRequest->get_ServerVariables(&m_piServerVariables))
{
CComVariant name;
CComVariant result;
name = "HTTP_USER_AGENT\0";
if (SUCCEEDED(m_piServerVariables->get_Item(name, &result)))
{
VariantChangeType(&result, &result, 0, VT_BSTR);
*pVal = ::SysAllocString(result.bstrVal);
}
}
return S_OK;
}
これで、UserAgent プロパティを参照すると、HTTP_USER_AGENT の値を返すコンポーネントのできあがりです。