RegisterActiveObject関数は内部でRunning Object Table (ROT)を使っていると、MSDNライブラリにも書かれてあります: Registration Functions (Automation)

ROTは、モニカーをキーとしてオブジェクトを登録する、つまり連想配列のようなものです。ならば、クラスIDをキーに登録するRegisterActiveObjectはどういうモニカーでROTに登録するのか、ということを知りたくなりました。

調べた結果、クラスIDの文字列のアイテムモニカーであることが分かりました。すなわち、モニカーの文字列表現は"!{XXXXXXXX-……}"という形式になります。

今回のサンプルプログラムは、RegisterActiveObjectで登録したオブジェクトをIRunningObjectTable::GetObjectで取り出したり、IRunningObjectTable::Registerで登録したオブジェクトをGetActiveObjectで取り出したりするというものです。

#define UNICODE
#define _UNICODE
#define WIN32_LEAN_AND_MEAN
#define _ATL_NO_AUTOMATIC_NAMESPACE
 
#include <iostream>
#include <cstdlib>
#include <windows.h>
#include <atlbase.h>
#include <atlcom.h>
#include <atlutil.h>
 
// {EECAE0DA-5F2B-48E2-9F22-09A788DA83FE}
static const GUID CLSID_Hoge =
{
  0xeecae0da, 0x5f2b, 0x48e2,
  { 0x9f, 0x22, 0x9, 0xa7, 0x88, 0xda, 0x83, 0xfe }
};
 
struct Hoge : IUnknown
{
  IFACEMETHOD(QueryInterface)(REFIID riid, void** ppv) override
  {
    if (riid == IID_IUnknown)
    {
      *ppv = (IUnknown*)this;
      return S_OK;
    }
    return E_NOINTERFACE;
  }
  IFACEMETHOD_(DWORD, AddRef)() override { return 1; }
  IFACEMETHOD_(DWORD, Release)() override { return 1; }
};
 
void ExitIfFailed(_In_ PCWSTR functionName, HRESULT hr)
{
  if (SUCCEEDED(hr))
  {
    return;
  }
  std::wclog << functionName << '\n';
  std::wclog << std::showbase << std::hex << hr << '\n';
  std::wclog << ATL::AtlGetErrorDescription(hr).GetString() << std::endl;
  std::quick_exit(static_cast<int>(hr));
}
 
int main()
{
  std::wclog.imbue(std::locale(""));
  auto hrInit = CoInitializeEx(
    nullptr, COINIT_MULTITHREADED | COINIT_DISABLE_OLE1DDE);
  ExitIfFailed(L"CoInitializeEx", hrInit);
 
  ATL::CComPtr<IRunningObjectTable> rot;
  auto hrRot = GetRunningObjectTable(0, &rot);
  ExitIfFailed(L"GetRunningObjectTable", hrRot);
 
  ATL::CComPtr<IMoniker> mk;
  auto hrMk = CreateItemMoniker(
    L"!", L"{EECAE0DA-5F2B-48E2-9F22-09A788DA83FE}", &mk);
  ExitIfFailed(L"CreateItemMoniker", hrMk);
 
  std::cout << std::boolalpha;
  {
    Hoge obj;
    DWORD reg;
    auto hrReg = RegisterActiveObject(
      &obj, CLSID_Hoge, ACTIVEOBJECT_STRONG, &reg);
    ExitIfFailed(L"RegisterActiveObject", hrReg);
 
    ATL::CComPtr<IUnknown> unk;
    auto hrGet = rot->GetObject(mk, &unk);
    ExitIfFailed(L"IRunningObjectTable::GetObject", hrGet);
 
    std::cout << unk.IsEqualObject(&obj) << std::endl;
 
    RevokeActiveObject(reg, nullptr);
  }
  {
    Hoge obj2;
    DWORD reg;
    auto hrReg = rot->Register(
      ROTFLAGS_REGISTRATIONKEEPSALIVE, &obj2, mk, &reg);
    ExitIfFailed(L"RegisterActiveObject", hrReg);
 
    ATL::CComPtr<IUnknown> unk;
    auto hrGet = GetActiveObject(CLSID_Hoge, nullptr, &unk);
    ExitIfFailed(L"GetActiveObject", hrGet);
 
    std::cout << unk.IsEqualObject(&obj2) << std::endl;
 
    rot->Revoke(reg);
  }
  std::quick_exit(0);
}

クラスモニカーを使っているのかと思っていましたが、その予想は外れてしまいました。


スポンサード リンク

この記事のカテゴリ

  • ⇒ RegisterActiveObjectとROT
  • ⇒ RegisterActiveObjectとROT
  • ⇒ RegisterActiveObjectとROT