今回は、前回予告した、IProfferServiceを使い、WebBrowserコントロールにIInternetSecurityManagerを提供する方法の話です。
WebBrowserコントロールでのIProfferServiceの使い方はこんな感じでした。
- WebBrowserコントロールのオブジェクトに対し、IServiceProvider.QueryServiceでSID_SProfferServiceを問い合わせ、IProfferServiceへのポインタを得る。
- IProfferService.ProfferServiceで、サービスのGUIDと自分が作成したIServiceProviderへのポインタを登録する。
その部分のコードです。
// class TestWindow内 LRESULT OnCreate(const CREATESTRUCT*) { constexpr DWORD IDC_WEBBROWSER_CONTROL = 1; RECT empty{}; m_webBrowser.Create(m_hWnd, empty, L"{8856F961-340A-11D0-A96B-00C04FD705A2}", WS_CHILD | WS_VISIBLE | WS_BORDER | WS_TABSTOP | WS_GROUP, 0, IDC_WEBBROWSER_CONTROL); ATL::CComPtr<IServiceProvider> sp; if (SUCCEEDED(m_webBrowser.QueryControl(&sp))) { ATL::CComPtr<IProfferService> ps; if (SUCCEEDED(sp->QueryService(SID_SProfferService, &ps))) { DWORD cookie; ATLENSURE_RETURN_VAL( SUCCEEDED(ps->ProfferService( SID_SInternetSecurityManagerEx2, &g_webBrowserServiceProvider, &cookie)), -1); m_webBrowserServiceCookie.push_back(cookie); ATLENSURE_RETURN_VAL( SUCCEEDED(ps->ProfferService( SID_SInternetSecurityManagerEx, &g_webBrowserServiceProvider, &cookie)), -1); m_webBrowserServiceCookie.push_back(cookie); ATLENSURE_RETURN_VAL( SUCCEEDED(ps->ProfferService( SID_SInternetSecurityManager, &g_webBrowserServiceProvider, &cookie)), -1); m_webBrowserServiceCookie.push_back(cookie); } } ATL::CComQIPtr<IWebBrowser2> wb = sp; ATL::CComVariant url(L"http://enable-javascript.com/ja/"); wb->Navigate2(&url, nullptr, nullptr, nullptr, nullptr); return 0; } void OnDestroy() { ATL::CComPtr<IServiceProvider> sp; if (SUCCEEDED(m_webBrowser.QueryControl(&sp))) { ATL::CComPtr<IProfferService> ps; if (SUCCEEDED(sp->QueryService(SID_SProfferService, &ps))) { for (auto cookie : m_webBrowserServiceCookie) { ps->RevokeService(cookie); } } } PostQuitMessage(0); } ATL::CAxWindow m_webBrowser; // boostを使いたくないなら、std::vector<DWORD>に変更する。 boost::container::static_vector<DWORD, 3> m_webBrowserServiceCookie; |
ここ以外は、前回と全く同じコードです。そのコード全部を次に載せます。
#define UNICODE #define _UNICODE #define WINVER 0x0501 #define _ATL_XP_TARGETING #define _ATL_NO_AUTOMATIC_NAMESPACE #define _WTL_NO_AUTOMATIC_NAMESPACE #include <cstdlib> #include <windows.h> #include <shobjidl.h> #include <atlbase.h> #include <atltypes.h> #include <atlwin.h> #include <atlapp.h> #include <atlcrack.h> // boostを使いたくないなら、#include <vector>に変更する。 #include <boost/container/static_vector.hpp> class Module : public ATL::CAtlExeModuleT<Module> { }; Module module; class ATL_NO_VTABLE UntrustedSecurityManager : public ATL::CComObjectRootEx<ATL::CComSingleThreadModel>, public IInternetSecurityManagerEx2 { public: BEGIN_COM_MAP(UntrustedSecurityManager) COM_INTERFACE_ENTRY(IInternetSecurityManager) COM_INTERFACE_ENTRY(IInternetSecurityManagerEx) COM_INTERFACE_ENTRY(IInternetSecurityManagerEx2) END_COM_MAP() IFACEMETHOD(SetSecuritySite)( _In_opt_ IInternetSecurityMgrSite* /*pSite*/) override { return INET_E_DEFAULT_ACTION; } IFACEMETHOD(GetSecuritySite)( _Out_ IInternetSecurityMgrSite** /*ppSite*/) override { return INET_E_DEFAULT_ACTION; } IFACEMETHOD(MapUrlToZone)( _In_ LPCWSTR /*pwszUrl*/, _Out_ DWORD* pdwZone, DWORD /*dwFlags*/) override { *pdwZone = URLZONE_UNTRUSTED; return S_OK; } IFACEMETHOD(GetSecurityId)( _In_ LPCWSTR /*pwszUrl*/, _Out_writes_bytes_to_(MAX_SIZE_SECURITY_ID, *pcbSecurityId) BYTE* /*pbSecurityId*/, _Inout_ _At_(*pcbSecurityId, _In_range_(>= , MAX_SIZE_SECURITY_ID) _Out_range_(0, MAX_SIZE_SECURITY_ID)) DWORD* /*pcbSecurityId*/, _In_ DWORD_PTR /*dwReserved*/) override { return INET_E_DEFAULT_ACTION; } IFACEMETHOD(ProcessUrlAction)( _In_ LPCWSTR pwszUrl, DWORD dwAction, _Out_writes_(cbPolicy) BYTE* pPolicy, DWORD cbPolicy, _In_opt_ BYTE* pContext, DWORD cbContext, DWORD dwFlags, DWORD dwReserved) override { DWORD flags; return ProcessUrlActionEx(pwszUrl, dwAction, pPolicy, cbPolicy, pContext, cbContext, dwFlags, dwReserved, &flags); } IFACEMETHOD(QueryCustomPolicy)( _In_ LPCWSTR /*pwszUrl*/, _In_ REFGUID /*guidKey*/, /*__RPC__deref_out_ecount_full_opt(*pcbPolicy)*/ BYTE** /*ppPolicy*/, _Out_ DWORD* /*pcbPolicy*/, _In_ BYTE* /*pContext*/, DWORD /*cbContext*/, DWORD /*dwReserved*/) override { return INET_E_DEFAULT_ACTION; } IFACEMETHOD(SetZoneMapping)( DWORD /*dwZone*/, _In_ LPCWSTR /*lpszPattern*/, DWORD /*dwFlags*/) override { return INET_E_DEFAULT_ACTION; } IFACEMETHOD(GetZoneMappings)( DWORD /*dwZone*/, __RPC__deref_out_opt IEnumString** /*ppenumString*/, DWORD /*dwFlags*/) override { return INET_E_DEFAULT_ACTION; } IFACEMETHOD(ProcessUrlActionEx)( _In_ LPCWSTR /*pwszUrl*/, DWORD /*dwAction*/, __RPC__out_ecount_full(cbPolicy) BYTE* pPolicy, DWORD cbPolicy, _In_ BYTE* /*pContext*/, DWORD /*cbContext*/, DWORD /*dwFlags*/, DWORD /*dwReserved*/, _Out_ DWORD* pdwOutFlags) override { if (pdwOutFlags != nullptr) { *pdwOutFlags = PUAFOUT_DEFAULT; } if (cbPolicy == sizeof(DWORD)) { *reinterpret_cast<DWORD*>(pPolicy) = URLPOLICY_DISALLOW; return S_FALSE; } return INET_E_DEFAULT_ACTION; } IFACEMETHOD(MapUrlToZoneEx2)( _In_ IUri* /*pUri*/, _Out_ DWORD* pdwZone, DWORD /*dwFlags*/, _Outptr_opt_ LPWSTR* ppwszMappedUrl, _Out_opt_ DWORD* pdwOutFlags) override { if (ppwszMappedUrl != nullptr) { *ppwszMappedUrl = nullptr; } if (pdwOutFlags != nullptr) { *pdwOutFlags = 0; } if (pdwZone != nullptr) { *pdwZone = URLZONE_UNTRUSTED; } return S_OK; } IFACEMETHOD(ProcessUrlActionEx2)( _In_ IUri* /*pUri*/, DWORD dwAction, __RPC__out_ecount_full(cbPolicy) BYTE* pPolicy, DWORD cbPolicy, _In_opt_ BYTE* pContext, DWORD cbContext, DWORD dwFlags, DWORD_PTR dwReserved, _Out_ DWORD* pdwOutFlags) override { return ProcessUrlActionEx(L"", dwAction, pPolicy, cbPolicy, pContext, cbContext, dwFlags, dwReserved, pdwOutFlags); } IFACEMETHOD(GetSecurityIdEx2)( _In_ IUri* /*pUri*/, /*_Out_writes_bytes_to_(MAX_SIZE_SECURITY_ID, *pcbSecurityId)*/ BYTE* /*pbSecurityId*/, /*_Inout_ _At_(*pcbSecurityId, _In_range_(>= , MAX_SIZE_SECURITY_ID) _Out_range_(0, MAX_SIZE_SECURITY_ID))*/ DWORD* /*pcbSecurityId*/, _In_ DWORD_PTR /*dwReserved*/) override { return INET_E_DEFAULT_ACTION; } IFACEMETHOD(QueryCustomPolicyEx2)( _In_ IUri* /*pUri*/, _In_ REFGUID /*guidKey*/, __RPC__deref_out_ecount_full_opt(*pcbPolicy) BYTE** /*ppPolicy*/, _Out_ DWORD* /*pcbPolicy*/, _In_ BYTE* /*pContext*/, DWORD /*cbContext*/, DWORD_PTR /*dwReserved*/) override { return INET_E_DEFAULT_ACTION; } }; class ATL_NO_VTABLE WebBrowserServiceProvider : public ATL::CComObjectRootEx<ATL::CComSingleThreadModel>, public IServiceProvider { public: BEGIN_COM_MAP(WebBrowserServiceProvider) COM_INTERFACE_ENTRY(IServiceProvider) END_COM_MAP() public: IFACEMETHOD(QueryService)( _In_ REFGUID guidService, _In_ REFIID riid, _COM_Outptr_ void** ppv) override { if (guidService == SID_SInternetSecurityManager || guidService == SID_SInternetSecurityManagerEx || guidService == SID_SInternetSecurityManagerEx2) { return m_untrustedSecurityManager.QueryInterface(riid, ppv); } return E_NOINTERFACE; } private: ATL::CComObjectStackEx<UntrustedSecurityManager> m_untrustedSecurityManager; }; ATL::CComObjectStackEx<WebBrowserServiceProvider> g_webBrowserServiceProvider; class TestWindow : public ATL::CWindowImpl<TestWindow>, public WTL::CMessageFilter { public: int Run(int cmdShow, _Inout_ WTL::CMessageLoop& msgLoop) { if (!Create(nullptr, ATL::CWindow::rcDefault, TEXT("Hello, world"), WS_OVERLAPPEDWINDOW)) { return -1; } ShowWindow(cmdShow); UpdateWindow(); msgLoop.AddMessageFilter(this); return msgLoop.Run(); } BOOL PreTranslateMessage(_In_ MSG* pmsg) override { if (m_webBrowser.IsWindow() && m_webBrowser.SendMessage( WM_FORWARDMSG, 0, reinterpret_cast<LPARAM>(pmsg))) { return TRUE; } return IsDialogMessage(pmsg); } DECLARE_WND_CLASS(TEXT("Test Window Class")); BEGIN_MSG_MAP(TestWindow) MSG_WM_SIZE(OnSize) MSG_WM_SETFOCUS(OnSetFocus) MSG_WM_CREATE(OnCreate) MSG_WM_DESTROY(OnDestroy) END_MSG_MAP() private: void OnSize(UINT, SIZE size) { m_webBrowser.ResizeClient(size.cx, size.cy); } void OnSetFocus(HWND) { m_webBrowser.SetFocus(); } LRESULT OnCreate(const CREATESTRUCT*) { constexpr DWORD IDC_WEBBROWSER_CONTROL = 1; RECT empty{}; m_webBrowser.Create(m_hWnd, empty, L"{8856F961-340A-11D0-A96B-00C04FD705A2}", WS_CHILD | WS_VISIBLE | WS_BORDER | WS_TABSTOP | WS_GROUP, 0, IDC_WEBBROWSER_CONTROL); ATL::CComPtr<IServiceProvider> sp; if (SUCCEEDED(m_webBrowser.QueryControl(&sp))) { ATL::CComPtr<IProfferService> ps; if (SUCCEEDED(sp->QueryService(SID_SProfferService, &ps))) { DWORD cookie; ATLENSURE_RETURN_VAL( SUCCEEDED(ps->ProfferService( SID_SInternetSecurityManagerEx2, &g_webBrowserServiceProvider, &cookie)), -1); m_webBrowserServiceCookie.push_back(cookie); ATLENSURE_RETURN_VAL( SUCCEEDED(ps->ProfferService( SID_SInternetSecurityManagerEx, &g_webBrowserServiceProvider, &cookie)), -1); m_webBrowserServiceCookie.push_back(cookie); ATLENSURE_RETURN_VAL( SUCCEEDED(ps->ProfferService( SID_SInternetSecurityManager, &g_webBrowserServiceProvider, &cookie)), -1); m_webBrowserServiceCookie.push_back(cookie); } } ATL::CComQIPtr<IWebBrowser2> wb = sp; ATL::CComVariant url(L"http://enable-javascript.com/ja/"); wb->Navigate2(&url, nullptr, nullptr, nullptr, nullptr); return 0; } void OnDestroy() { ATL::CComPtr<IServiceProvider> sp; if (SUCCEEDED(m_webBrowser.QueryControl(&sp))) { ATL::CComPtr<IProfferService> ps; if (SUCCEEDED(sp->QueryService(SID_SProfferService, &ps))) { for (auto cookie : m_webBrowserServiceCookie) { ps->RevokeService(cookie); } } } PostQuitMessage(0); } ATL::CAxWindow m_webBrowser; // boostを使いたくないなら、std::vector<DWORD>に変更する。 boost::container::static_vector<DWORD, 3> m_webBrowserServiceCookie; }; int WINAPI WinMain(HINSTANCE, HINSTANCE, LPSTR, int cmdShow) { if (FAILED(OleInitialize(nullptr))) { std::quick_exit(-1); } WTL::CMessageLoop msgLoop; TestWindow wnd; std::quick_exit(wnd.Run(cmdShow, msgLoop)); } |
前回より少し手順が複雑です。その代わり、ATL::CAxWindowやATL::CAxHostWindowなどの内部実装を知る必要が無いのが利点です。
今回のIProfferServiceを使う方法は、C# Tips -AxWebBrowserのIInternetSecurityManager-で知りました。この方法をC++でやってみたということになります。
MSDNライブラリの項目へのリンクです: IProfferService interface。
スポンサード リンク |