本記事は、COM Advent Calendar 2014 – Qiitaの18日目の記事です。


今日は、現在実行中のスレッドのアパートメントの種類を知る方法です。

まず、Windows 7からCoGetApartmentType関数があります。それとATLにATL::AtlGetApartmentType関数があります。

#include <iostream>
#include <windows.h>
#include <shlwapi.h>
#define _ATL_NO_AUTOMATIC_NAMESPACE
 
#include <iostream>
#include <atlbase.h>
#include <atlcom.h>
 
int main()
{
  std::cout << std::boolalpha;
#if 1
  DWORD coInit = COINIT_MULTITHREADED;
#else
  DWORD coInit = COINIT_APARTMENTTHREADED;
#endif
  if (FAILED(CoInitializeEx(nullptr, coInit | COINIT_DISABLE_OLE1DDE)))
  {
    return 1;
  }
 
  APTTYPE aptType;
  APTTYPEQUALIFIER aptQualifier;
  if (SUCCEEDED(CoGetApartmentType(&aptType, &aptQualifier)))
  {
    std::cout << "CoGetApartmentType" << std::endl;
    std::cout << "Is STA: "
      << (aptType == APTTYPE_STA || aptType == APTTYPE_MAINSTA) << std::endl;
    std::cout << "Is MTA: " << (aptType == APTTYPE_MTA) << std::endl;
  }
  std::cout << "--------" << std::endl;
  DWORD apartmentType;
  if (ATL::AtlGetApartmentType(&apartmentType))
  {
    std::cout << "ATL::AtlGetApartmentType" << std::endl;
    std::cout << "Is STA: "
      << (apartmentType == COINIT_APARTMENTTHREADED) << std::endl;
    std::cout << "Is MTA: "
      << (apartmentType == COINIT_MULTITHREADED) << std::endl;
  }
 
  CoUninitialize();
}

実行結果は次のとおりになります。

CoGetApartmentType
Is STA: false
Is MTA: true
--------
ATL::AtlGetApartmentType
Is STA: false
Is MTA: true

本Advent Calendarで珍しく個別のライブラリであるATLの関数を取り上げた理由は、CoInitialize関数の挙動をうまく使っているので実装を紹介したいと思ったからです。以下に引用します。

// Returns the apartment type that the current thread is in. false is returned
// if the thread isn't in an apartment.
inline _Success_(return != false)
bool AtlGetApartmentType(_Out_ DWORD* pApartmentType)
{
    HRESULT hr = CoInitialize(NULL);
    if (SUCCEEDED(hr))
        CoUninitialize();
 
    if (hr == S_FALSE)
    {
        *pApartmentType = COINIT_APARTMENTTHREADED;
        return true;
    }
    else if (hr == RPC_E_CHANGED_MODE)
    {   
        *pApartmentType = COINIT_MULTITHREADED;
        return true;
    }
 
    return false;
}

CoGetApartmentTypeと違ってNAなどの判定ができませんが、STAとMTA(と未初期化)の区別が付けば十分な場合はこれで満たせます。もちろん、Windows 7未満で動作するのも利点です。


スポンサード リンク

この記事のカテゴリ

  • ⇒ 今いるアパートメントの種類を知りたい