summaryrefslogtreecommitdiffstats
path: root/webkit/activex_shim/web_activex_site.cc
diff options
context:
space:
mode:
authorinitial.commit <initial.commit@0039d316-1c4b-4281-b951-d872f2087c98>2008-07-27 00:20:51 +0000
committerinitial.commit <initial.commit@0039d316-1c4b-4281-b951-d872f2087c98>2008-07-27 00:20:51 +0000
commitf5b16fed647e941aa66933178da85db2860d639b (patch)
treef00e9856c04aad3b558a140955e7674add33f051 /webkit/activex_shim/web_activex_site.cc
parent920c091ac3ee15079194c82ae8a7a18215f3f23c (diff)
downloadchromium_src-f5b16fed647e941aa66933178da85db2860d639b.zip
chromium_src-f5b16fed647e941aa66933178da85db2860d639b.tar.gz
chromium_src-f5b16fed647e941aa66933178da85db2860d639b.tar.bz2
Add webkit to the repository.
git-svn-id: svn://svn.chromium.org/chrome/trunk/src@18 0039d316-1c4b-4281-b951-d872f2087c98
Diffstat (limited to 'webkit/activex_shim/web_activex_site.cc')
-rw-r--r--webkit/activex_shim/web_activex_site.cc692
1 files changed, 692 insertions, 0 deletions
diff --git a/webkit/activex_shim/web_activex_site.cc b/webkit/activex_shim/web_activex_site.cc
new file mode 100644
index 0000000..85bf675
--- /dev/null
+++ b/webkit/activex_shim/web_activex_site.cc
@@ -0,0 +1,692 @@
+// Copyright 2008, Google Inc.
+// All rights reserved.
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+// * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+// * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+// * Neither the name of Google Inc. nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+#include "webkit/activex_shim/web_activex_site.h"
+
+#include <exdisp.h>
+#include <oaidl.h>
+#include <shlguid.h>
+
+#include "base/string_util.h"
+#include "webkit/activex_shim/activex_plugin.h"
+#include "webkit/activex_shim/npp_impl.h"
+#include "webkit/activex_shim/web_activex_container.h"
+
+namespace activex_shim {
+
+// WebActiveXSite
+WebActiveXSite::WebActiveXSite()
+ : container_(NULL),
+ control_(NULL),
+ inplace_activated_(false),
+ has_capture_(false) {
+ rect_.left = 0;
+ rect_.top = 0;
+ rect_.right = 0;
+ rect_.bottom = 0;
+}
+
+WebActiveXSite::~WebActiveXSite() {
+ // Don't do anything here. Do everything in FinalRelease.
+}
+
+void WebActiveXSite::Init(WebActiveXContainer* container, IUnknown* control) {
+ container_ = container;
+ control_.Attach(control);
+ dispatch_ = control;
+ ole_object_ = control;
+ inplace_object_ = control;
+ view_object_ = control;
+ inplace_object_windowless_ = control;
+}
+
+void WebActiveXSite::FinalRelease() {
+ // We must release everything here instead of leaving it to the destructor.
+ // Otherwise crash is possible.
+ if (control_ != NULL) {
+ dispatch_.Release();
+ view_object_.Release();
+ inplace_object_windowless_.Release();
+ if (inplace_object_ != NULL) {
+ if (inplace_activated_) {
+ // If we just deactivate without checking whether the control has been
+ // inplace activated, the control may behave irratically. Flash will
+ // decrease its reference count during deactivation. Thus causing
+ // crash when we try to release it later.
+ inplace_object_->InPlaceDeactivate();
+ inplace_activated_ = false;
+ }
+ inplace_object_.Release();
+ }
+ if (ole_object_ != NULL) {
+ ole_object_->SetClientSite(NULL);
+ ole_object_->Close(OLECLOSE_NOSAVE);
+ ole_object_.Release();
+ }
+ long ref = control_.Detach()->Release();
+ // It should be 0 otherwise we have incorrect ref counting.
+ // Shockwave is known to have ref counting problems. All other controls
+ // behave well.
+ DCHECK(ref == 0 || container_->plugin()->activex_type()
+ == ACTIVEX_SHOCKWAVE);
+ }
+}
+
+HRESULT WebActiveXSite::ActivateControl(
+ int x, int y, int width, int height,
+ const std::vector<ControlParam>& params) {
+ // Set the rect size of site first before SetClientSite. Otherwise the
+ // control may query the site for such information during SetClientSite.
+ rect_.left = x;
+ rect_.top = y;
+ rect_.right = rect_.left + width;
+ rect_.bottom = rect_.top + height;
+
+ HRESULT hr;
+ if (ole_object_ != NULL) {
+ hr = ole_object_->SetClientSite(static_cast<IOleClientSite*>(this));
+ if (FAILED(hr))
+ return hr;
+ }
+ SetExtent(width, height);
+
+ // Set initial properties.
+ CComQIPtr<IPersistPropertyBag> persist_property_bag = control_;
+ CComQIPtr<IPersistPropertyBag2> persist_property_bag2 = control_;
+ if (persist_property_bag2 != NULL || persist_property_bag != NULL) {
+ // Use property bag for initialization. This is the preferred way.
+ initial_params_ = params;
+ // Use bag2 first.
+ if (persist_property_bag2 != NULL) {
+ persist_property_bag2->InitNew();
+ hr = persist_property_bag2->Load(this, NULL);
+ DCHECK(SUCCEEDED(hr));
+ } else {
+ persist_property_bag->InitNew();
+ hr = persist_property_bag->Load(this, NULL);
+ DCHECK(SUCCEEDED(hr));
+ }
+ // We don't need this anymore.
+ initial_params_.clear();
+ } else if (dispatch_ != NULL) {
+ // Use the dispatch interface to set the initial properties. This is
+ // less efficient for most controls.
+ for (unsigned int i = 0; i < params.size(); ++i) {
+ const ControlParam& param = params[i];
+ VARIANT vtvalue;
+ // TODO(ruijiang): Think about type conversion.
+ vtvalue.vt = VT_BSTR;
+ vtvalue.bstrVal = SysAllocString(param.value.c_str());
+ DispSetProperty(dispatch_, param.name.c_str(), vtvalue);
+ VariantClear(&vtvalue);
+ }
+ }
+
+ // In place activate it if it is able to.
+ if (inplace_object_ != NULL) {
+ hr = DoVerb(OLEIVERB_INPLACEACTIVATE);
+ if (FAILED(hr))
+ return hr;
+ }
+
+ return S_OK;
+}
+
+HRESULT WebActiveXSite::DoVerb(long verb) {
+ if (ole_object_ != NULL) {
+ HRESULT hr = ole_object_->DoVerb(verb, NULL,
+ static_cast<IOleClientSite*>(this), 0,
+ container_->container_wnd(), &rect_);
+ if (verb == OLEIVERB_INPLACEACTIVATE && SUCCEEDED(hr))
+ inplace_activated_ = true;
+ return hr;
+ } else {
+ return E_UNEXPECTED;
+ }
+}
+
+HRESULT WebActiveXSite::SetExtent(int width, int height) {
+ if (ole_object_ != NULL) {
+ SIZEL size;
+ if (width < 0)
+ width = 0;
+ if (height < 0)
+ height = 0;
+ ScreenToHimetric(width, height, &size);
+ return ole_object_->SetExtent(DVASPECT_CONTENT, &size);
+ } else {
+ return E_UNEXPECTED;
+ }
+}
+
+void WebActiveXSite::SetRect(const RECT* rect) {
+ if (EqualRect(&rect_, rect))
+ return;
+ SetExtent(rect->right - rect->left, rect->bottom - rect->top);
+ if (inplace_object_ != NULL) {
+ inplace_object_->SetObjectRects(rect, rect);
+ rect_ = *rect;
+ }
+}
+
+// IUnknown
+HRESULT STDMETHODCALLTYPE WebActiveXSite::QueryInterface(REFIID iid,
+ void** object) {
+ *object = NULL;
+ if (iid == IID_IUnknown) {
+ // Avoid ambiguous resolution of IUnknown.
+ *object = static_cast<IUnknown*>(static_cast<MinimumIDispatchImpl*>(this));
+ } else if (iid == IID_IDispatch) {
+ *object = static_cast<MinimumIDispatchImpl*>(this);
+ } else if (iid == IID_IOleClientSite) {
+ *object = static_cast<IOleClientSite*>(this);
+ } else if (iid == IID_IOleControlSite) {
+ *object = static_cast<IOleControlSite*>(this);
+ } else if (iid == IID_IOleInPlaceSite) {
+ *object = static_cast<IOleInPlaceSite*>(this);
+ } else if (iid == IID_IOleInPlaceSiteEx) {
+ *object = static_cast<IOleInPlaceSiteEx*>(this);
+ } else if (iid == IID_IOleInPlaceSiteWindowless) {
+ if (container_->plugin()->windowless())
+ *object = static_cast<IOleInPlaceSiteWindowless*>(this);
+ } else if (iid == IID_IServiceProvider) {
+ *object = static_cast<IServiceProvider*>(this);
+ } else if (iid == IID_IPropertyBag) {
+ *object = static_cast<IPropertyBag*>(this);
+ } else if (iid == IID_IPropertyBag2) {
+ *object = static_cast<IPropertyBag2*>(this);
+ }
+ TRACK_QUERY_INTERFACE(iid, *object != NULL);
+ return (*object != NULL) ? S_OK : E_NOINTERFACE;
+}
+
+// IOleClientSite
+HRESULT STDMETHODCALLTYPE WebActiveXSite::SaveObject() {
+ // Do not support saving object to persistant storage.
+ return E_NOTIMPL;
+}
+
+// Even though Flash will call this method to get the url, it will not use
+// the url to resolve its movie path.
+// However, according to http://support.microsoft.com/kb/181678, this is
+// a valid way of getting url from ActiveX control.
+HRESULT STDMETHODCALLTYPE WebActiveXSite::GetMoniker(
+ DWORD assign,
+ DWORD which_moniker,
+ IMoniker** moniker) {
+ TRACK_METHOD();
+ if (which_moniker == OLEWHICHMK_CONTAINER) {
+ std::wstring url = container_->plugin()->GetCurrentURL();
+ HRESULT hr = CreateURLMoniker(NULL, url.c_str(), moniker);
+ return hr;
+ } else {
+ return E_FAIL;
+ }
+}
+
+HRESULT STDMETHODCALLTYPE WebActiveXSite::GetContainer(
+ IOleContainer** container) {
+ *container = container_;
+ return S_OK;
+}
+
+HRESULT STDMETHODCALLTYPE WebActiveXSite::ShowObject() {
+ TRACK_METHOD();
+ // The control asks us to show the object which we already did.
+ return S_OK;
+};
+
+HRESULT STDMETHODCALLTYPE WebActiveXSite::OnShowWindow(BOOL show) {
+ TRACK_METHOD();
+ // Doesn't apply to us.
+ return S_OK;
+};
+
+HRESULT STDMETHODCALLTYPE WebActiveXSite::RequestNewObjectLayout() {
+ TRACK_METHOD();
+ // As MSDN says: "Currently, there is no standard mechanism by which
+ // a container can negotiate how much room an object would like. When
+ // such a negotiation is defined, responding to this method will be
+ // optional for containers."
+ return E_NOTIMPL;
+}
+
+// IOleControlSite
+HRESULT STDMETHODCALLTYPE WebActiveXSite::OnControlInfoChanged() {
+ TRACK_METHOD();
+ // As we do not support mnemonics, we do not need to retrieve control info.
+ // This may change in the future though.
+ return S_OK;
+}
+
+HRESULT STDMETHODCALLTYPE WebActiveXSite::LockInPlaceActive(BOOL lock) {
+ TRACK_METHOD();
+ // We don't support this.
+ return E_NOTIMPL;
+}
+
+HRESULT STDMETHODCALLTYPE WebActiveXSite::GetExtendedControl(IDispatch** disp) {
+ TRACK_METHOD();
+ // We do not support extended control.
+ return E_NOTIMPL;
+}
+
+HRESULT STDMETHODCALLTYPE WebActiveXSite::TransformCoords(POINTL* ptl_himetric,
+ POINTF* ptf_container,
+ DWORD flags) {
+ TRACK_METHOD();
+ // TODO(ruijiang): so far haven't found anyone use this yet. Be aware and
+ // add support if needed.
+ return E_NOTIMPL;
+}
+
+HRESULT STDMETHODCALLTYPE WebActiveXSite::TranslateAccelerator(
+ MSG* msg,
+ DWORD modifiers) {
+ TRACK_METHOD();
+ // It would be nice if controls call this and let me process accelerator
+ // first. But unfortunately all of them I tested don't. So let's ignore
+ // and just keep an eye on it.
+ return E_NOTIMPL;
+}
+
+HRESULT STDMETHODCALLTYPE WebActiveXSite::OnFocus(BOOL got_focus) {
+ TRACK_METHOD();
+ return S_OK;
+}
+
+HRESULT STDMETHODCALLTYPE WebActiveXSite::ShowPropertyFrame() {
+ TRACK_METHOD();
+ // No we don't want to show property sheet.
+ return E_NOTIMPL;
+}
+
+// IOleWindow
+
+HRESULT STDMETHODCALLTYPE WebActiveXSite::GetWindow(HWND* wnd) {
+ *wnd = container_->container_wnd();
+ return S_OK;
+}
+
+HRESULT STDMETHODCALLTYPE WebActiveXSite::ContextSensitiveHelp(
+ BOOL enter_mode) {
+ // Do not support this.
+ return E_NOTIMPL;
+}
+
+// IOleInPlaceSite
+
+HRESULT STDMETHODCALLTYPE WebActiveXSite::CanInPlaceActivate() {
+ TRACK_METHOD();
+ return S_OK;
+}
+
+HRESULT STDMETHODCALLTYPE WebActiveXSite::OnInPlaceActivate() {
+ TRACK_METHOD();
+ return S_OK;
+}
+
+HRESULT STDMETHODCALLTYPE WebActiveXSite::OnInPlaceDeactivate() {
+ TRACK_METHOD();
+ return S_OK;
+}
+
+HRESULT STDMETHODCALLTYPE WebActiveXSite::OnUIActivate() {
+ TRACK_METHOD();
+ // If we have multiple sites in a container we may deactivate the previous
+ // active control. This is not a requirement though.
+ return S_OK;
+}
+
+HRESULT STDMETHODCALLTYPE WebActiveXSite::OnUIDeactivate(BOOL undoable) {
+ TRACK_METHOD();
+ // Some controls will call this when they lose focus. Right now we don't need
+ // to do anything about it.
+ return S_OK;
+}
+
+HRESULT STDMETHODCALLTYPE WebActiveXSite::GetWindowContext(
+ IOleInPlaceFrame** frame,
+ IOleInPlaceUIWindow** doc,
+ LPRECT pos,
+ LPRECT clip,
+ LPOLEINPLACEFRAMEINFO frame_info) {
+ TRACK_METHOD();
+ if (frame) {
+ *frame = container_;
+ }
+ if (doc)
+ *doc = NULL;
+ if (pos)
+ *pos = rect_;
+ if (clip)
+ *clip = rect_;
+ if (frame_info) {
+ frame_info->fMDIApp = FALSE;
+ frame_info->hwndFrame = container_->container_wnd();
+ frame_info->haccel = NULL;
+ frame_info->cAccelEntries = 0;
+ }
+ return S_OK;
+}
+
+HRESULT STDMETHODCALLTYPE WebActiveXSite::Scroll(SIZE scroll_extant) {
+ TRACK_METHOD();
+ return E_NOTIMPL;
+}
+
+HRESULT STDMETHODCALLTYPE WebActiveXSite::DiscardUndoState() {
+ TRACK_METHOD();
+ return S_OK;
+}
+
+HRESULT STDMETHODCALLTYPE WebActiveXSite::DeactivateAndUndo() {
+ TRACK_METHOD();
+ // Just let the object know that it's deactivated.
+ if (inplace_object_ != NULL)
+ inplace_object_->UIDeactivate();
+ return S_OK;
+}
+
+HRESULT STDMETHODCALLTYPE WebActiveXSite::OnPosRectChange(LPCRECT pos) {
+ TRACK_METHOD();
+ // We do not let the control move/resize itself. It should be controled
+ // by the container/browser.
+ return E_UNEXPECTED;
+}
+
+// IOleInPlaceSiteEx
+
+HRESULT STDMETHODCALLTYPE WebActiveXSite::OnInPlaceActivateEx(
+ BOOL* no_redraw,
+ DWORD flags) {
+ TRACK_METHOD();
+ // Redraw doesn't hurt.
+ if (no_redraw)
+ *no_redraw = FALSE;
+ if (flags & ACTIVATE_WINDOWLESS) {
+ // TODO(ruijiang): At this point we know for sure the object is activated
+ // as windowless. Revisit when we implement windowless controls.
+ }
+ return S_OK;
+}
+
+HRESULT STDMETHODCALLTYPE WebActiveXSite::OnInPlaceDeactivateEx(
+ BOOL no_redraw) {
+ TRACK_METHOD();
+ // See also: OnInPlaceDeactivate
+ return S_OK;
+}
+
+HRESULT STDMETHODCALLTYPE WebActiveXSite::RequestUIActivate() {
+ TRACK_METHOD();
+ return S_OK;
+}
+
+// IOleInPlaceSiteWindowless
+
+HRESULT STDMETHODCALLTYPE WebActiveXSite::CanWindowlessActivate() {
+ TRACK_METHOD();
+ // Yes, we prefer windowless activation.
+ return S_OK;
+}
+
+HRESULT STDMETHODCALLTYPE WebActiveXSite::GetCapture() {
+ TRACK_METHOD();
+ return has_capture_ ? S_OK : S_FALSE;
+}
+
+HRESULT STDMETHODCALLTYPE WebActiveXSite::SetCapture(BOOL capture) {
+ TRACK_METHOD();
+ // TODO(ruijiang): for now, let's cheat the control that it can always get
+ // what it wants (capture).
+ if (capture) {
+ has_capture_ = true;
+ return S_OK;
+ } else {
+ has_capture_ = false;
+ return S_OK;
+ }
+}
+
+HRESULT STDMETHODCALLTYPE WebActiveXSite::GetFocus() {
+ TRACK_METHOD();
+ // TODO(ruijiang): handle it.
+ return S_FALSE;
+}
+
+HRESULT STDMETHODCALLTYPE WebActiveXSite::SetFocus(BOOL focus) {
+ TRACK_METHOD();
+ // TODO(ruijiang): handle it.
+ if (focus) {
+ return S_FALSE;
+ } else {
+ return S_OK;
+ }
+}
+
+HRESULT STDMETHODCALLTYPE WebActiveXSite::GetDC(
+ LPCRECT rect,
+ DWORD flags,
+ HDC* dc) {
+ // It's probably not wise to get the dc of Chrome window and return it,
+ // because we always draw onto a memory dc. Thus we may have to disappoint
+ // the caller.
+ // TODO(ruijiang): We may enable this for other browsers like FireFox.
+ return E_FAIL;
+}
+
+HRESULT STDMETHODCALLTYPE WebActiveXSite::ReleaseDC(HDC dc) {
+ // TODO(ruijiang): We may enable this for other browsers like FireFox.
+ return E_FAIL;
+}
+
+HRESULT STDMETHODCALLTYPE WebActiveXSite::InvalidateRect(
+ LPCRECT rect,
+ BOOL erase) {
+ // This would be the rect (in client coord of the control) that we will
+ // invalidate.
+ RECT rc;
+ // Control's client area, start from top-left corner as 0.
+ RECT client = rect_;
+ OffsetRect(&client, -rect_.left, -rect_.top);
+ if (rect) {
+ RECT rc_in_client = *rect;
+ OffsetRect(&rc_in_client, -rect_.left, -rect_.top);
+ if (!IntersectRect(&rc, &rc_in_client, &client))
+ return S_OK;
+ } else {
+ rc = client;
+ }
+ // Convert it to NPRect. Now rc is relative to the upper-left corner of
+ // control. This is the requirement of NPN_InvalidateRect.
+ NPRect npr;
+ npr.left = static_cast<uint16>(rc.left);
+ npr.top = static_cast<uint16>(rc.top);
+ npr.right = static_cast<uint16>(rc.right);
+ npr.bottom = static_cast<uint16>(rc.bottom);
+ g_browser->invalidaterect(container_->plugin()->npp(), &npr);
+ return S_OK;
+}
+
+HRESULT STDMETHODCALLTYPE WebActiveXSite::InvalidateRgn(
+ HRGN rgn,
+ BOOL erase) {
+ TRACK_METHOD();
+ if (rgn == NULL) {
+ return InvalidateRect(NULL, erase);
+ } else {
+ // TODO(ruijiang): So far no one is using this function yet. So let's just
+ // invalidate the whole area. Optimize this when we need to.
+ return InvalidateRect(NULL, erase);
+ }
+}
+
+HRESULT STDMETHODCALLTYPE WebActiveXSite::ScrollRect(
+ INT dx,
+ INT dy,
+ LPCRECT scroll,
+ LPCRECT clip) {
+ TRACK_METHOD();
+ // TODO(ruijiang): revisit.
+ return E_NOTIMPL;
+}
+
+HRESULT STDMETHODCALLTYPE WebActiveXSite::AdjustRect(LPRECT rc) {
+ TRACK_METHOD();
+ // TODO(ruijiang): revisit.
+ return E_NOTIMPL;
+}
+
+HRESULT STDMETHODCALLTYPE WebActiveXSite::OnDefWindowMessage(
+ UINT msg,
+ WPARAM wparam,
+ LPARAM lparam,
+ LRESULT* result) {
+ TRACK_METHOD();
+ // TODO(ruijiang): handle it later.
+ return E_NOTIMPL;
+}
+
+// IServiceProvider
+HRESULT STDMETHODCALLTYPE WebActiveXSite::QueryService(
+ REFGUID guid,
+ REFIID riid,
+ void** object) {
+ HRESULT hr = E_FAIL;
+ // TODO(ruijiang): We may need to support SID_SWebBrowserApp and
+ // IID_IHTMLWindow2 in the future.
+ if (guid == IID_IBindHost || guid == IID_IWebBrowserApp)
+ hr = container_->QueryInterface(riid, object);
+ TRACK_QUERY_INTERFACE(riid, *object != NULL);
+ return hr;
+}
+
+// IPropertyBag
+HRESULT STDMETHODCALLTYPE WebActiveXSite::Read(LPCOLESTR prop_name,
+ VARIANT* var,
+ IErrorLog* err_log) {
+ unsigned int i;
+ for (i = 0; i < initial_params_.size(); ++i) {
+ if (_wcsicmp(prop_name, initial_params_[i].name.c_str()) == 0)
+ break;
+ }
+ if (i >= initial_params_.size())
+ return E_INVALIDARG;
+ if (var->vt == VT_EMPTY || var->vt == VT_BSTR) {
+ // We don't need to do any conversion in this case.
+ var->vt = VT_BSTR;
+ var->bstrVal = ::SysAllocString(initial_params_[i].value.c_str());
+ return S_OK;
+ } else {
+ // We need to try type conversion.
+ ScopedVariant org;
+ org.vt = VT_BSTR;
+ org.bstrVal = ::SysAllocString(initial_params_[i].value.c_str());
+ HRESULT hr = VariantChangeType(var, &org, 0, var->vt);
+ return FAILED(hr) ? E_FAIL : S_OK;
+ }
+}
+
+HRESULT STDMETHODCALLTYPE WebActiveXSite::Write(LPCOLESTR prop_name,
+ VARIANT* var) {
+ TRACK_METHOD();
+ return E_NOTIMPL;
+}
+
+// IPropertyBag2
+HRESULT STDMETHODCALLTYPE WebActiveXSite::Read(ULONG c_properties,
+ PROPBAG2* prop_bag,
+ IErrorLog* err_log,
+ VARIANT* value,
+ HRESULT* error) {
+ if (!prop_bag)
+ return E_INVALIDARG;
+ for (unsigned int i = 0; i < c_properties; ++i) {
+ PROPBAG2* p = prop_bag + i;
+ value->vt = p->vt;
+ HRESULT hr = Read(p->pstrName, value + i, err_log);
+ if (error)
+ error[i] = hr;
+ }
+ return S_OK;
+}
+
+HRESULT STDMETHODCALLTYPE WebActiveXSite::Write(ULONG c_properties,
+ PROPBAG2* prop_bag,
+ VARIANT* value) {
+ TRACK_METHOD();
+ return E_NOTIMPL;
+}
+
+HRESULT STDMETHODCALLTYPE WebActiveXSite::CountProperties(
+ ULONG* pc_properties) {
+ if (!pc_properties)
+ return E_INVALIDARG;
+ *pc_properties = static_cast<ULONG>(initial_params_.size());
+ return S_OK;
+}
+
+HRESULT STDMETHODCALLTYPE WebActiveXSite::GetPropertyInfo(
+ ULONG iproperty,
+ ULONG c_properties,
+ PROPBAG2* prop_bag,
+ ULONG* properties_returned) {
+ if (!prop_bag)
+ return E_INVALIDARG;
+ if (iproperty >= initial_params_.size())
+ return E_INVALIDARG;
+ unsigned int i;
+ for (i = iproperty;
+ i < iproperty + c_properties && i < initial_params_.size();
+ ++i) {
+ PROPBAG2* p = prop_bag + (i - iproperty);
+ memset(p, 0, sizeof(PROPBAG2));
+ p->dwType = PROPBAG2_TYPE_DATA;
+ p->vt = VT_BSTR;
+ p->cfType = CF_TEXT;
+ p->dwHint = iproperty;
+ // According to the document of IPropertyBag2::GetPropertyInfo, here
+ // requires a string allocated by CoTaskMemAlloc.
+ p->pstrName = CoTaskMemAllocString(initial_params_[i].name);
+ }
+ if (properties_returned)
+ *properties_returned = i - iproperty;
+ return S_OK;
+}
+
+HRESULT STDMETHODCALLTYPE WebActiveXSite::LoadObject(LPCOLESTR name,
+ DWORD hint,
+ IUnknown* unk_object,
+ IErrorLog* err_log) {
+ TRACK_METHOD();
+ return E_NOTIMPL;
+}
+
+} // namespace activex_shim