Using the sample code provided I reproduced the assertion.
It seems that when the RoInitializeWrapper class is used within the CheckTabletMode method the runtime wants the MTA to exist. After making the following addition for the MTA the CheckTabletMode method no longer asserted with error 0x80070776.
I used this helper class to create/destroy the MTA and used it within the CheckTabletMode method.
class CMTA {
public:
CO_MTA_USAGE_COOKIE cookie{};
HRESULT m_hr;
CMTA() : m_hr(CoIncrementMTAUsage(&cookie)) { }
~CMTA() { if (SUCCEEDED(m_hr)) CoDecrementMTAUsage(cookie); }
operator HRESULT() const { return m_hr; }
};
I also inserted a function to output the type of COM apartment that the thread was in after the RoInitializeWrapper object was instantiated.
void QueryApartmentType()
{
APTTYPE aType{};
APTTYPEQUALIFIER aQual{};
CString strApt, strQual;
HRESULT hr = CoGetApartmentType(&aType, &aQual);
_ASSERT(SUCCEEDED(hr));
switch (aType)
{
case APTTYPE_CURRENT:
strApt = _T("Current thread");
break;
case APTTYPE_STA:
strApt = _T("STA");
break;
case APTTYPE_MTA:
strApt = _T("MTA");
break;
case APTTYPE_NA:
strApt = _T("NA");
break;
case APTTYPE_MAINSTA:
strApt = _T("Main STA");
break;
}
switch (aQual)
{
case APTTYPEQUALIFIER_NONE:
strQual = _T("None");
break;
case APTTYPEQUALIFIER_IMPLICIT_MTA:
strQual = _T("Implicit MTA");
break;
case APTTYPEQUALIFIER_NA_ON_MTA:
strQual = _T("NA on MTA");
break;
case APTTYPEQUALIFIER_NA_ON_STA:
strQual = _T("NA on STA");
break;
case APTTYPEQUALIFIER_NA_ON_IMPLICIT_MTA:
strQual = _T("NA on Implicit MTA");
break;
case APTTYPEQUALIFIER_NA_ON_MAINSTA:
strQual = _T("NA on Main STA");
break;
case APTTYPEQUALIFIER_APPLICATION_STA:
strQual = _T("Application STA");
break;
case APTTYPEQUALIFIER_RESERVED_1:
strQual = _T("Reserved");
break;
}
TRACE(_T("Apartment type : %s, Apartment type qualifier : %s\n"), strApt, strQual);
}
This is where the above were inserted in the CheckTabletMode method -
bool CSampleDlg::CheckTabletMode(const bool bMultithreaded, const HWND hWnd)
{
//
// COM-Initialisierung
//
CMTA mta; // Create the MTA
_ASSERT(SUCCEEDED(mta));
RO_INIT_TYPE com_thread_initialization = RO_INIT_SINGLETHREADED;
if (bMultithreaded)
com_thread_initialization = RO_INIT_MULTITHREADED;
RoInitializeWrapper initialize(com_thread_initialization);
_ASSERT(SUCCEEDED(initialize));
if (FAILED(initialize))
{
SetLastError(0x1);
return false;
}
// What Apartment is this thread in
QueryApartmentType();