前回(保護モード+αなプロセスをCoCreateInstanceで作る(その1))の続きです。
今回は、もう1つの方法CLSCTX_ENABLE_CLOAKINGです。これは、CoCreateInstanceやCoGetClassObjectの実引数で指定する方法です。CoInitializeSecurityと違い、都度指定できる点が便利です。
ただし、Windows VistaからだとMSDNライブラリに書かれています(CLSCTX)。実際、Windows XPで使ってみるとHRESULT_FROM_WIN32でERROR_INVALID_PARAMETER、すなわち0x80070057が帰ってきて終わります。
クライアント側プログラムだけ掲載します。サーバー側は前回と同じです。このコードも前回との変更点は僅かです。CoInitializeSecurityを削り、CLSCTX_LOCAL_SERVER | CLSCTX_ENABLE_CLOAKINGを追加しただけです。
#define UNICODE #define _UNICODE #define WIN32_LEAN_AND_MEAN #define _ATL_NO_AUTOMATIC_NAMESPACE #define _ATL_XP_TARGETING #include <iostream> #include <windows.h> #include <VersionHelpers.h> #include <atlbase.h> #include <atlcom.h> #include <atlutil.h> #include <boost/scope_exit.hpp> #include <boost/implicit_cast.hpp> // {DCC853C7-52FD-446E-8BFC-6662D97FD935} static const GUID CLSID_Hoge = { 0xdcc853c7, 0x52fd, 0x446e, { 0x8b, 0xfc, 0x66, 0x62, 0xd9, 0x7f, 0xd9, 0x35 } }; HRESULT OutputErrorMessgae(_In_ PCWSTR functionName, HRESULT hr) { std::wclog << functionName << '\n'; std::wclog << std::showbase << std::hex << hr << '\n'; std::wclog << ATL::AtlGetErrorDescription(hr).GetString() << std::endl; return hr; } HRESULT OutputLastError(_In_ PCWSTR functionName) { auto hr = ATL::AtlHresultFromLastError(); OutputErrorMessgae(functionName, hr); return hr; } HANDLE CreateProtectedToken() { ATL::CHandle hOriginalToken, hToken; if (!OpenProcessToken(GetCurrentProcess(), TOKEN_ASSIGN_PRIMARY | TOKEN_DUPLICATE | TOKEN_QUERY | TOKEN_ADJUST_DEFAULT, &hOriginalToken.m_h)) { OutputLastError(L"OpenProcessToken"); return nullptr; } DWORD flags = DISABLE_MAX_PRIVILEGE; if (IsWindowsVistaOrGreater()) { flags |= LUA_TOKEN; } if (!CreateRestrictedToken(hOriginalToken, flags, 0, nullptr, 0, nullptr, 0, nullptr, &hToken.m_h)) { OutputLastError(L"CreateRestrictedToken"); return nullptr; } if (IsWindowsVistaOrGreater()) { SID lowIL{ SID_REVISION, 1, SECURITY_MANDATORY_LABEL_AUTHORITY, SECURITY_MANDATORY_LOW_RID, }; TOKEN_MANDATORY_LABEL tml{ { &lowIL, SE_GROUP_INTEGRITY, }, }; if (!SetTokenInformation( hToken, TokenIntegrityLevel, &tml, sizeof tml)) { OutputLastError(L"SetTokenInformation"); return nullptr; } } return hToken.Detach(); } ATL::CComPtr<IDispatch> CreateHoge() { ATL::CHandle hToken(CreateProtectedToken()); if (!ImpersonateLoggedOnUser(hToken)) { throw ATL::CAtlException(OutputLastError(L"ImpersonateLoggedOnUser")); } BOOST_SCOPE_EXIT_ALL(&hToken) { if (!RevertToSelf()) { abort(); } }; ATL::CComPtr<IDispatch> obj; #if 0 // 1にしても動きます。 ATL::CComPtr<IClassFactory> cf; ATLENSURE_SUCCEEDED( CoGetClassObject(CLSID_Hoge, CLSCTX_LOCAL_SERVER | CLSCTX_ENABLE_CLOAKING, nullptr, IID_PPV_ARGS(&cf))); ATLENSURE_SUCCEEDED(cf->CreateInstance(nullptr, IID_PPV_ARGS(&obj))); #else ATLENSURE_SUCCEEDED(obj.CoCreateInstance(CLSID_Hoge, nullptr, CLSCTX_LOCAL_SERVER | CLSCTX_ENABLE_CLOAKING)); #endif return obj; } int main() { std::locale loc(std::locale::classic(), "", std::locale::ctype); std::wclog.imbue(loc); std::wcout.imbue(loc); try { ATLENSURE_SUCCEEDED(CoInitializeEx( nullptr, COINIT_MULTITHREADED | COINIT_DISABLE_OLE1DDE)); auto obj = CreateHoge(); ATL::CComVariant v; DISPID dispid = DISPID_VALUE; ATLENSURE_SUCCEEDED(obj.Invoke0(dispid, &v)); ATLENSURE_SUCCEEDED(v.ChangeType(VT_BSTR)); if (v.bstrVal != nullptr) { std::wcout << v.bstrVal << std::endl; } std::cin.get(); } catch(const ATL::CAtlException& e) { std::wclog << std::hex << std::showbase << e.m_hr << std::endl; std::wclog << boost::implicit_cast<PCWSTR>( ATL::AtlGetErrorDescription(e)) << std::endl; } CoUninitialize(); } |
上記ではCLSCTX_LOCAL_SERVERにしましたが、CLSCTX_ALLとの組み合わせでもうまくいきました。
その2でいったん終わりにしようかと考えています。その3もあるのですが、少し別手法なので、しばらく間をおいてから(ほかに書きたいことを先に取り上げてから)にしようと思います。
スポンサード リンク |