/*
Plugin of Miranda IM for communicating with users of the MSN Messenger protocol.
Copyright (c) 2012-2017 Miranda NG Team
Copyright (c) 2007-2012 Boris Krasnovskiy.
This program is free software; you can redistribute it and/or
modify it under the terms of the GNU General Public License
as published by the Free Software Foundation; either version 2
of the License, or (at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see .
*/
#include "stdafx.h"
#include
#include "msn_proto.h"
#include "msn_ieembed.h"
IEEmbedSink::IEEmbedSink(IEEmbed *smptr)
{
ieWindow = smptr;
}
IEEmbedSink::~IEEmbedSink() {}
STDMETHODIMP IEEmbedSink::QueryInterface(REFIID riid, PVOID *ppv)
{
*ppv = nullptr;
if (IID_IUnknown == riid)
*ppv = (IUnknown *)this;
if (IID_IDispatch == riid)
*ppv = (IDispatch *)this;
if (DIID_DWebBrowserEvents2 == riid)
*ppv = (DWebBrowserEvents2*)this;
if (nullptr != *ppv) {
((LPUNKNOWN)*ppv)->AddRef();
return NOERROR;
}
return E_NOINTERFACE;
}
STDMETHODIMP_(ULONG) IEEmbedSink::AddRef(void)
{
++m_cRef;
return m_cRef;
}
STDMETHODIMP_(ULONG) IEEmbedSink::Release(void)
{
--m_cRef;
return m_cRef;
}
STDMETHODIMP IEEmbedSink::GetTypeInfoCount(UINT *) { return E_NOTIMPL; }
STDMETHODIMP IEEmbedSink::GetTypeInfo(UINT, LCID, LPTYPEINFO*) { return S_OK; }
STDMETHODIMP IEEmbedSink::GetIDsOfNames(REFIID, LPOLESTR*, UINT, LCID, DISPID*) { return S_OK; }
STDMETHODIMP IEEmbedSink::Invoke(DISPID dispIdMember, REFIID, LCID, WORD, DISPPARAMS* pDispParams, VARIANT*, EXCEPINFO*, UINT*)
{
if (!pDispParams) return E_INVALIDARG;
switch (dispIdMember) {
case DISPID_DOCUMENTCOMPLETE:
DocumentComplete(
pDispParams->rgvarg[1].pdispVal,
pDispParams->rgvarg[0].pvarVal);
return S_OK;
}
return DISP_E_MEMBERNOTFOUND;
}
// DWebBrowserEvents2
void IEEmbedSink::StatusTextChange(BSTR) {}
void IEEmbedSink::ProgressChange(long, long) {}
void IEEmbedSink::CommandStateChange(long, VARIANT_BOOL) {}
void IEEmbedSink::DownloadBegin() {}
void IEEmbedSink::DownloadComplete() {}
void IEEmbedSink::TitleChange(BSTR) {}
void IEEmbedSink::PropertyChange(BSTR) {}
void IEEmbedSink::BeforeNavigate2(IDispatch*, VARIANT* , VARIANT*, VARIANT*, VARIANT*, VARIANT*, VARIANT_BOOL*) { }
void IEEmbedSink::NewWindow2(IDispatch**, VARIANT_BOOL*) {}
void IEEmbedSink::NavigateComplete(IDispatch*, VARIANT*) {}
void IEEmbedSink::DocumentComplete(IDispatch* , VARIANT* url)
{
HWND hWnd;
ieWindow->GetWindow(&hWnd);
SendMessage(hWnd, UM_DOCCOMPLETE, 0, (LPARAM)url->bstrVal);
}
void IEEmbedSink::OnQuit() {}
void IEEmbedSink::OnVisible(VARIANT_BOOL) {}
void IEEmbedSink::OnToolBar(VARIANT_BOOL) {}
void IEEmbedSink::OnMenuBar(VARIANT_BOOL) {}
void IEEmbedSink::OnStatusBar(VARIANT_BOOL) {}
void IEEmbedSink::OnFullScreen(VARIANT_BOOL) {}
void IEEmbedSink::OnTheaterMode(VARIANT_BOOL) {}
void IEEmbedSink::WindowSetResizable(VARIANT_BOOL) {}
void IEEmbedSink::WindowSetLeft(long) {}
void IEEmbedSink::WindowSetTop(long) {}
void IEEmbedSink::WindowSetWidth(long) {}
void IEEmbedSink::WindowSetHeight(long) {}
void IEEmbedSink::WindowClosing(VARIANT_BOOL, VARIANT_BOOL*) {}
void IEEmbedSink::ClientToHostWindow(long *, long *) {}
void IEEmbedSink::SetSecureLockIcon(long) {}
void IEEmbedSink::FileDownload(VARIANT_BOOL*) {}
static LRESULT CALLBACK IEEmbedServerWindowProcedure(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)
{
IEEmbed **view = (IEEmbed **)GetWindowLongPtr(GetParent(GetParent(GetParent(hwnd))), GWLP_USERDATA);
if (view && *view) {
switch (message) {
/*
case WM_KEYUP:
if (LOWORD(wParam) == VK_ESCAPE && !(GetKeyState(VK_SHIFT) & 0x8000) && !(GetKeyState(VK_CONTROL) & 0x8000) && !(GetKeyState(VK_MENU) & 0x8000))
SendMessage(GetParent(GetParent(GetParent(hwnd))), WM_COMMAND, IDCANCEL, 0);
break; */
case WM_KEYDOWN:
if (LOWORD(wParam) != VK_BACK)
(*view)->translateAccelerator(message, wParam, lParam);
break;
/*
case WM_SETFOCUS:
RECT rcWindow;
POINT cursor;
GetWindowRect(hwnd, &rcWindow);
GetCursorPos(&cursor);
if (cursor.y <= rcWindow.bottom && cursor.y >= rcWindow.top && cursor.x <= rcWindow.right && cursor.x >= rcWindow.left)
view->mouseActivate();
if (view->setFocus((HWND)wParam))
return TRUE;
break;
*/
}
return CallWindowProc((*view)->getServerWndProc(), hwnd, message, wParam, lParam);
}
return DefWindowProc(hwnd, message, wParam, lParam);
}
static LRESULT CALLBACK IEEmbedDocWindowProcedure(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)
{
IEEmbed **view = (IEEmbed **)GetWindowLongPtr(GetParent(GetParent(hwnd)), GWLP_USERDATA);
if (view && *view) {
WNDPROC oldWndProc = (*view)->getDocWndProc();
if (message == WM_PARENTNOTIFY && wParam == WM_CREATE) {
SetWindowLongPtr(hwnd, GWLP_WNDPROC, (LONG_PTR)oldWndProc);
(*view)->setServerWndProc((WNDPROC)SetWindowLongPtr((HWND)lParam, GWLP_WNDPROC, (LONG_PTR)IEEmbedServerWindowProcedure));
}
return CallWindowProc(oldWndProc, hwnd, message, wParam, lParam);
}
return DefWindowProc(hwnd, message, wParam, lParam);
}
static LRESULT CALLBACK IEEmbedWindowProcedure(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)
{
IEEmbed **view = (IEEmbed **)GetWindowLongPtr(GetParent(hwnd), GWLP_USERDATA);
if (view && *view) {
WNDPROC oldWndProc = (*view)->getMainWndProc();
if (message == WM_PARENTNOTIFY && wParam == WM_CREATE) {
SetWindowLongPtr(hwnd, GWLP_WNDPROC, (LONG_PTR)oldWndProc);
(*view)->setDocWndProc((WNDPROC)SetWindowLongPtr((HWND)lParam, GWLP_WNDPROC, (LONG_PTR)IEEmbedDocWindowProcedure));
}
return CallWindowProc(oldWndProc, hwnd, message, wParam, lParam);
}
return DefWindowProc(hwnd, message, wParam, lParam);
}
IEEmbed::IEEmbed(HWND _parent)
{
MSG msg;
parent = _parent;
GetClientRect(_parent, &rcClient);
if (SUCCEEDED(pWebBrowser.CoCreateInstance(CLSID_WebBrowser, nullptr, CLSCTX_INPROC))) {
CComPtr pOleObject;
if (SUCCEEDED(pWebBrowser.QueryInterface(&pOleObject))) {
pOleObject->SetClientSite(this);
pOleObject->DoVerb(OLEIVERB_INPLACEACTIVATE, &msg, this, 0, this->parent, &rcClient);
}
else MessageBox(nullptr, TranslateT("IID_IOleObject failed."), TranslateT("RESULT"), MB_OK);
CComPtr pOleInPlace;
if (SUCCEEDED(pWebBrowser.QueryInterface(&pOleInPlace)))
pOleInPlace->GetWindow(&hwnd);
else
MessageBox(nullptr, TranslateT("IID_IOleInPlaceObject failed."), TranslateT("RESULT"), MB_OK);
//setBorder();
CComPtr pCPContainer;
// Step 1: Get a pointer to the connection point container.
if (SUCCEEDED(pWebBrowser.QueryInterface(&pCPContainer))) {
// m_pConnectionPoint is defined like this:
// Step 2: Find the connection point.
if (SUCCEEDED(pCPContainer->FindConnectionPoint(DIID_DWebBrowserEvents2, &m_pConnectionPoint))) {
// Step 3: Advise the connection point that you
// want to sink its events.
sink = new IEEmbedSink(this);
if (FAILED(m_pConnectionPoint->Advise(sink, &m_dwCookie)))
MessageBox(nullptr, TranslateT("Failed to Advise"), TranslateT("C++ Event Sink"), MB_OK);
}
}
setMainWndProc((WNDPROC)SetWindowLongPtr(hwnd, GWLP_WNDPROC, (LONG_PTR)IEEmbedWindowProcedure));
SetFocus(hwnd);
}
pWebBrowser->put_RegisterAsDropTarget(VARIANT_FALSE);
}
IEEmbed::~IEEmbed()
{
CComPtr pOleObject;
if (SUCCEEDED(pWebBrowser.QueryInterface(&pOleObject)))
pOleObject->SetClientSite(nullptr);
else
MessageBox(nullptr, TranslateT("IID_IOleObject failed."), TranslateT("RESULT"), MB_OK);
if (m_pConnectionPoint != nullptr)
m_pConnectionPoint->Unadvise(m_dwCookie);
if (sink != nullptr)
delete sink;
DestroyWindow(hwnd);
}
void IEEmbed::ResizeBrowser()
{
CComPtr pOleInPlace;
GetClientRect(parent, &rcClient);
if (SUCCEEDED(pWebBrowser.QueryInterface(&pOleInPlace)))
pOleInPlace->SetObjectRects(&rcClient, &rcClient);
}
// IUnknown
STDMETHODIMP IEEmbed::QueryInterface(REFIID riid, PVOID *ppv)
{
*ppv = nullptr;
if (IID_IUnknown == riid)
*ppv = this;
if (IID_IOleClientSite == riid)
*ppv = (IOleClientSite*)this;//Unknown)m_pIOleClientSite;
if (IID_IOleWindow == riid || IID_IOleInPlaceSite == riid)
*ppv = (IOleInPlaceSite*)this;//m_pIOleIPSite;
if (nullptr != *ppv) {
((LPUNKNOWN)*ppv)->AddRef();
return NOERROR;
}
return E_NOINTERFACE;
}
STDMETHODIMP_(ULONG) IEEmbed::AddRef(void)
{
++m_cRef;
return m_cRef;
}
STDMETHODIMP_(ULONG) IEEmbed::Release(void)
{
--m_cRef;
return m_cRef;
}
// IDispatch
STDMETHODIMP IEEmbed::GetTypeInfoCount(UINT *) { return E_NOTIMPL; }
STDMETHODIMP IEEmbed::GetTypeInfo(UINT, LCID, LPTYPEINFO*) { return S_OK; }
STDMETHODIMP IEEmbed::GetIDsOfNames(REFIID, LPOLESTR*, UINT, LCID, DISPID*) { return S_OK; }
STDMETHODIMP IEEmbed::Invoke(DISPID, REFIID, LCID, WORD, DISPPARAMS*, VARIANT*, EXCEPINFO*, UINT*) { return DISP_E_MEMBERNOTFOUND; }
// IOleWindow
STDMETHODIMP IEEmbed::GetWindow(HWND *phwnd)
{
*phwnd = parent;
return S_OK;
}
STDMETHODIMP IEEmbed::ContextSensitiveHelp(BOOL) { return E_NOTIMPL; }
STDMETHODIMP IEEmbed::CanInPlaceActivate(void) { return S_OK; }
STDMETHODIMP IEEmbed::OnInPlaceActivate(void) { return S_OK; }
STDMETHODIMP IEEmbed::OnUIActivate(void) { return E_NOTIMPL; }
STDMETHODIMP IEEmbed::GetWindowContext(IOleInPlaceFrame **, IOleInPlaceUIWindow **, LPRECT lprcPosRect, LPRECT lprcClipRect, LPOLEINPLACEFRAMEINFO)
{
lprcPosRect->left = rcClient.left;
lprcPosRect->top = rcClient.top;
lprcPosRect->right = rcClient.right;
lprcPosRect->bottom = rcClient.bottom;
lprcClipRect->left = rcClient.left;
lprcClipRect->top = rcClient.top;
lprcClipRect->right = rcClient.right;
lprcClipRect->bottom = rcClient.bottom;
return S_OK;
}
STDMETHODIMP IEEmbed::Scroll(SIZE) { return E_NOTIMPL; }
STDMETHODIMP IEEmbed::OnUIDeactivate(BOOL) { return E_NOTIMPL; }
STDMETHODIMP IEEmbed::OnInPlaceDeactivate(void) { return S_OK; }
STDMETHODIMP IEEmbed::DiscardUndoState(void) { return E_NOTIMPL; }
STDMETHODIMP IEEmbed::DeactivateAndUndo(void) { return E_NOTIMPL; }
STDMETHODIMP IEEmbed::OnPosRectChange(LPCRECT) { return E_NOTIMPL; }
STDMETHODIMP IEEmbed::SaveObject(void) { return E_NOTIMPL; }
STDMETHODIMP IEEmbed::GetMoniker(DWORD, DWORD, IMoniker **) { return E_NOTIMPL; }
STDMETHODIMP IEEmbed::GetContainer(IOleContainer **) { return E_NOTIMPL; }
STDMETHODIMP IEEmbed::ShowObject(void) { return E_NOTIMPL; }
STDMETHODIMP IEEmbed::OnShowWindow(BOOL) { return E_NOTIMPL; }
STDMETHODIMP IEEmbed::RequestNewObjectLayout(void) { return E_NOTIMPL; }
void IEEmbed::setMainWndProc(WNDPROC wndProc)
{
mainWndProc = wndProc;
}
WNDPROC IEEmbed::getMainWndProc()
{
return mainWndProc;
}
void IEEmbed::setDocWndProc(WNDPROC wndProc)
{
docWndProc = wndProc;
}
WNDPROC IEEmbed::getDocWndProc()
{
return docWndProc;
}
void IEEmbed::setServerWndProc(WNDPROC wndProc)
{
serverWndProc = wndProc;
}
WNDPROC IEEmbed::getServerWndProc()
{
return serverWndProc;
}
void IEEmbed::write(const wchar_t *text)
{
CComPtr document = getDocument();
if (!document) return;
SAFEARRAY *safe_array = ::SafeArrayCreateVector(VT_VARIANT, 0, 1);
if (safe_array != nullptr) {
VARIANT *variant;
::SafeArrayAccessData(safe_array, (LPVOID *)&variant);
variant->vt = VT_BSTR;
variant->bstrVal = ::SysAllocString(text);
::SafeArrayUnaccessData(safe_array);
document->write(safe_array);
// ::SysFreeString(bstr); // don't free it !!!!!!!
::SafeArrayDestroy(safe_array);
document->close();
}
}
void IEEmbed::addCookie(const wchar_t *cookieString)
{
CComPtr document = getDocument();
if (!document) return;
BSTR cookie = SysAllocString(cookieString);
document->put_cookie(cookie);
SysFreeString(cookie);
}
BSTR IEEmbed::getCookies()
{
CComPtr document = getDocument();
BSTR cookie = nullptr;
if (!document) return nullptr;
document->get_cookie(&cookie);
return cookie;
}
IHTMLDocument2* IEEmbed::getDocument()
{
CComPtr dispatch;
if (SUCCEEDED(pWebBrowser->get_Document(&dispatch)) && dispatch != nullptr) {
CComPtr document;
dispatch.QueryInterface(&document);
return document.Detach();
}
return nullptr;
}
void IEEmbed::navigate(const wchar_t *url)
{
pWebBrowser->Navigate((WCHAR *)url, nullptr, nullptr, nullptr, nullptr);
}
void IEEmbed::navigate(char *url)
{
wchar_t *pwszUrl = mir_a2u(url);
navigate(pwszUrl);
mir_free(pwszUrl);
}
void IEEmbed::navigate(NETLIBHTTPREQUEST *nlhr)
{
WCHAR *szUrl = mir_a2u(nlhr->szUrl);
BSTR bstrHeaders;
LPSAFEARRAY psa;
LPSTR pPostData;
VARIANT vPostData = {0}, vHeaders = {0};
bstrHeaders = SysAllocString(L"Content-Type: application/x-www-form-urlencoded\r\n");
V_VT(&vHeaders) = VT_BSTR;
V_BSTR(&vHeaders) = bstrHeaders;
VariantInit(&vPostData);
psa = SafeArrayCreateVector(VT_UI1, 0, nlhr->dataLength);
SafeArrayAccessData(psa, (LPVOID*)&pPostData);
memcpy(pPostData, nlhr->pData, nlhr->dataLength);
SafeArrayUnaccessData(psa);
V_VT(&vPostData) = VT_ARRAY | VT_UI1;
V_ARRAY(&vPostData) = psa;
pWebBrowser->Navigate(szUrl, nullptr, nullptr, &vPostData, &vHeaders);
SysFreeString(bstrHeaders);
VariantClear(&vPostData);
mir_free(szUrl);
}
char *IEEmbed::GetHTMLDoc() {
CComPtr spDispDoc;
char *pszRet = nullptr;
if (SUCCEEDED(pWebBrowser->get_Document(&spDispDoc))) {
CComPtr spDoc;
if (SUCCEEDED(spDispDoc->QueryInterface(IID_IHTMLDocument3, (void**)&spDoc))) {
CComPtr spRootElement;
if (SUCCEEDED(spDoc->get_documentElement(&spRootElement)))
{
BSTR bstrDoc;
if (SUCCEEDED(spRootElement->get_outerHTML(&bstrDoc)))
{
pszRet = mir_u2a(bstrDoc);
SysFreeString(bstrDoc);
}
}
}
}
return pszRet;
}
void IEEmbed::translateAccelerator(UINT uMsg, WPARAM wParam, LPARAM lParam)
{
CComPtr pIOIPAO;
if (SUCCEEDED(pWebBrowser.QueryInterface(&pIOIPAO))) {
MSG msg;
msg.message = uMsg;
msg.wParam = wParam;
msg.lParam = lParam;
pIOIPAO->TranslateAccelerator(&msg);
}
}