blob: 8c5dd2808ea4b2d56a5980f5155d8de85c4982ac [file] [log] [blame]
/*
* Copyright 2008 Google Inc.
*
* Licensed under the Apache License, Version 2.0 (the "License"); you may not
* use this file except in compliance with the License. You may obtain a copy of
* the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
* License for the specific language governing permissions and limitations under
* the License.
*/
#pragma once
#include "stdafx.h"
#include "comutil.h"
#include "dispex.h"
#include "SessionData.h"
#define SYSLOGERROR(MSG,FMT,...) \
LPCWSTR msgArr[3] = {NULL, NULL, NULL}; \
msgArr[0] = MSG; \
WCHAR buffer1[512]; \
swprintf(buffer1, sizeof(buffer1)/sizeof(WCHAR), FMT, __VA_ARGS__); \
msgArr[1] = buffer1; \
WCHAR buffer2[512]; \
swprintf(buffer2, sizeof(buffer2)/sizeof(WCHAR), L"function: %S, file: %S, line: %d", __FUNCTION__, __FILE__, __LINE__); \
msgArr[2] = buffer2; \
IEUtils::WriteToLog((LPCWSTR*)msgArr, 3);
typedef HRESULT (*PFNRESOLVENAME)(IDispatch*, LPOLESTR, DISPID*);
//
// This class is a collection of helper methods specific to IE
// It finds the appropriate implementation that resolves javascript
// names regardless of the specific documentMode that browser is
// running.
//
class IEUtils
{
static HANDLE hEventLog;
static LPWSTR logSourceName;
static PFNRESOLVENAME pfnResolveName;
//
// finds which IDispatch interface is capable of
// of 'resolving' names.
//
static PFNRESOLVENAME getResolveNameFunction(IDispatch* obj)
{
_variant_t retVal;
std::string probeScript("function _FN3E9738B048214100A6D6B750F2230A34() { return null; }");
CComQIPtr<IHTMLWindow2> spWindow2(obj);
if (!spWindow2) {
return &IEUtils::internalResolveNameEx;
}
LPOLESTR functionName = L"_FN3E9738B048214100A6D6B750F2230A34";
HRESULT hr = spWindow2->execScript(UTF8ToBSTR(probeScript.length(), probeScript.c_str()),
UTF8ToBSTR(10, "JavaScript"), retVal.GetAddress());
if (SUCCEEDED(hr)) {
DISPID dispId;
hr = internalResolveName(spWindow2, functionName, &dispId);
if (SUCCEEDED(hr)) {
return &IEUtils::internalResolveName;
} else {
hr = internalResolveNameEx(spWindow2, functionName, &dispId);
if (SUCCEEDED(hr)) {
return &IEUtils::internalResolveNameEx;
} else {
SYSLOGERROR(L"Failed to find a IDispatch Implementation able to resolve names",
L"hr=0x%08x", hr);
}
}
}
return &IEUtils::internalResolveNameEx;
}
//
// resolves 'name' using default IDispatch interface
//
static HRESULT internalResolveName(IDispatch* obj, LPOLESTR name, DISPID *dispID)
{
assert(obj != NULL);
return obj->GetIDsOfNames(IID_NULL, &name, 1, LOCALE_SYSTEM_DEFAULT, dispID);
}
//
// resolves 'name' using IDispatchEx interface
//
static HRESULT internalResolveNameEx(IDispatch* obj, LPOLESTR name, DISPID *dispID)
{
assert(obj != NULL);
CComQIPtr<IDispatchEx> spDispEx(obj);
if (!spDispEx) {
return E_FAIL;
}
return spDispEx->GetIDsOfNames(IID_NULL, &name, 1, LOCALE_SYSTEM_DEFAULT, dispID);
}
public:
static void InitEventLog() {
if (NULL == hEventLog) {
hEventLog = OpenEventLog(NULL, IEUtils::logSourceName);
}
}
static void WriteToLog(LPCWSTR* rgMsg, INT size) {
if (NULL != hEventLog) {
ReportEvent(hEventLog, EVENTLOG_ERROR_TYPE, 0, 0, NULL, size, 0, rgMsg, NULL);
}
}
static void CloseEventLog()
{
if (NULL != hEventLog) {
::CloseEventLog(hEventLog);
}
}
static WCHAR* GetSysErrorMessage(DWORD dwErrorCode)
{
WCHAR * pMsgBuf = NULL;
DWORD dwSize = FormatMessage(FORMAT_MESSAGE_FROM_SYSTEM |
FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_IGNORE_INSERTS,
NULL, dwErrorCode, 0, (LPTSTR) &pMsgBuf, 0, NULL);
if (dwSize) {
return pMsgBuf;
}
return NULL;
}
static HRESULT resolveName(IDispatch* obj, LPOLESTR name, DISPID *dispID)
{
if (NULL == pfnResolveName) {
pfnResolveName = getResolveNameFunction(obj);
}
assert(NULL != pfnResolveName);
return pfnResolveName(obj, name, dispID);
}
static HRESULT resolveName(IDispatch* obj, std::string name, DISPID *dispID)
{
return resolveName(obj, UTF8ToBSTR(name.length(), name.c_str()), dispID);
}
static void resetResolver()
{
pfnResolveName = NULL;
}
static HRESULT Invoke(IUnknown* obj,
DISPID id,
WORD wFlags,
DISPPARAMS *pdp,
VARIANT *pvarRes,
EXCEPINFO *pei,
UINT *puArgErr)
{
HRESULT hr = S_OK;
CComQIPtr<IDispatchEx> spDispEx(obj);
if (!spDispEx) {
return E_FAIL;
}
hr = spDispEx->Invoke(id, IID_NULL, LOCALE_SYSTEM_DEFAULT, wFlags, pdp, pvarRes, pei, puArgErr);
return hr;
}
};
__declspec(selectany) HANDLE IEUtils::hEventLog;
__declspec(selectany) LPWSTR IEUtils::logSourceName = L"GWT Developer Mode Plugin";
__declspec(selectany) HRESULT (*IEUtils::pfnResolveName)(IDispatch* object, LPOLESTR name, DISPID *dispID);