1
/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*-
2
* ***** BEGIN LICENSE BLOCK *****
3
* Version: MPL 1.1/GPL 2.0/LGPL 2.1
5
* The contents of this file are subject to the Mozilla Public License Version
6
* 1.1 (the "License"); you may not use this file except in compliance with
7
* the License. You may obtain a copy of the License at
8
* http://www.mozilla.org/MPL/
10
* Software distributed under the License is distributed on an "AS IS" basis,
11
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
12
* for the specific language governing rights and limitations under the
15
* The Original Code is the IDispatch implementation for XPConnect.
17
* The Initial Developer of the Original Code is
19
* Portions created by the Initial Developer are Copyright (C) 2002
20
* the Initial Developer. All Rights Reserved.
24
* Alternatively, the contents of this file may be used under the terms of
25
* either the GNU General Public License Version 2 or later (the "GPL"), or
26
* the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
27
* in which case the provisions of the GPL or the LGPL are applicable instead
28
* of those above. If you wish to allow use of your version of this file only
29
* under the terms of either the GPL or the LGPL, and not to allow others to
30
* use your version of this file under the terms of the MPL, indicate your
31
* decision by deleting the provisions above and replace them with the notice
32
* and other provisions required by the GPL or the LGPL. If you do not delete
33
* the provisions above, a recipient may use your version of this file under
34
* the terms of any one of the MPL, the GPL or the LGPL.
36
* ***** END LICENSE BLOCK ***** */
39
* \file nsDispatchSupport.cpp
40
* Contains the implementation for the nsDispatchSupport class
41
* this is an XPCOM service
44
#include "XPCPrivate.h"
46
#include "nsIActiveXSecurityPolicy.h"
49
ClassIsListed(HKEY hkeyRoot, const TCHAR *szKey, const CLSID &clsid, PRBool &listIsEmpty)
51
// Test if the specified CLSID is found in the specified registry key
53
listIsEmpty = PR_TRUE;
56
if(keyList.Open(hkeyRoot, szKey, KEY_READ) != ERROR_SUCCESS)
58
// Class is not listed, because there is no key to read!
62
// Enumerate CLSIDs looking for this one
67
const DWORD kBufLength = sizeof(szCLSID) / sizeof(szCLSID[0]);
68
memset(szCLSID, 0, sizeof(szCLSID));
69
if(::RegEnumKey(keyList, i, szCLSID, kBufLength) != ERROR_SUCCESS)
75
listIsEmpty = PR_FALSE;
76
szCLSID[kBufLength - 1] = TCHAR('\0');
77
CLSID clsidToCompare = GUID_NULL;
78
if(SUCCEEDED(::CLSIDFromString(T2OLE(szCLSID), &clsidToCompare)) &&
79
::IsEqualCLSID(clsid, clsidToCompare))
91
ClassExists(const CLSID &clsid)
93
// Test if there is a CLSID entry. If there isn't then obviously
94
// the object doesn't exist.
96
if(key.Open(HKEY_CLASSES_ROOT, _T("CLSID"), KEY_READ) != ERROR_SUCCESS)
97
return PR_FALSE; // Must fail if we can't even open this!
99
LPOLESTR szCLSID = NULL;
100
if(FAILED(StringFromCLSID(clsid, &szCLSID)))
101
return PR_FALSE; // Can't allocate string from CLSID
105
LONG lResult = keyCLSID.Open(key, W2CT(szCLSID), KEY_READ);
106
CoTaskMemFree(szCLSID);
107
if(lResult != ERROR_SUCCESS)
108
return PR_FALSE; // Class doesn't exist
114
ClassImplementsCategory(const CLSID &clsid, const CATID &catid, PRBool &bClassExists)
116
bClassExists = ClassExists(clsid);
117
// Non existent classes won't implement any category...
121
// CLSID exists, so try checking what categories it implements
122
bClassExists = PR_TRUE;
123
CComPtr<ICatInformation> catInfo;
124
HRESULT hr = CoCreateInstance(CLSID_StdComponentCategoriesMgr, NULL,
125
CLSCTX_INPROC_SERVER, __uuidof(ICatInformation), (LPVOID*) &catInfo);
127
return PR_FALSE; // Must fail if we can't open the category manager
129
// See what categories the class implements
130
CComPtr<IEnumCATID> enumCATID;
131
if(FAILED(catInfo->EnumImplCategoriesOfClass(clsid, &enumCATID)))
132
return PR_FALSE; // Can't enumerate classes in category so fail
134
// Search for matching categories
136
CATID catidNext = GUID_NULL;
137
while(enumCATID->Next(1, &catidNext, NULL) == S_OK)
139
if(::IsEqualCATID(catid, catidNext))
140
return PR_TRUE; // Match
145
nsDispatchSupport* nsDispatchSupport::mInstance = nsnull;
147
NS_IMPL_THREADSAFE_ISUPPORTS1(nsDispatchSupport, nsIDispatchSupport)
149
nsDispatchSupport::nsDispatchSupport()
151
/* member initializers and constructor code */
154
nsDispatchSupport::~nsDispatchSupport()
156
/* destructor code */
160
* Converts a COM variant to a jsval
161
* @param comvar the variant to convert
162
* @param val pointer to the jsval to receive the value
165
NS_IMETHODIMP nsDispatchSupport::COMVariant2JSVal(VARIANT * comvar, jsval *val)
167
XPCCallContext ccx(NATIVE_CALLER);
169
XPCDispConvert::COMToJS(ccx, *comvar, *val, retval);
174
* Converts a jsval to a COM variant
175
* @param val the jsval to be converted
176
* @param comvar pointer to the variant to receive the value
179
NS_IMETHODIMP nsDispatchSupport::JSVal2COMVariant(jsval val, VARIANT * comvar)
181
XPCCallContext ccx(NATIVE_CALLER);
183
XPCDispConvert::JSToCOM(ccx, val, *comvar, retval);
187
/* boolean isClassSafeToHost (in nsCIDRef clsid, out boolean classExists); */
188
NS_IMETHODIMP nsDispatchSupport::IsClassSafeToHost(JSContext * cx,
190
PRBool ignoreException,
194
NS_ENSURE_ARG_POINTER(aResult);
195
NS_ENSURE_ARG_POINTER(classExists);
199
CLSID clsid = XPCDispnsCID2CLSID(cid);
201
// Ask security manager if it's ok to create this object
202
XPCCallContext ccx(JS_CALLER, cx);
203
nsIXPCSecurityManager* sm =
204
ccx.GetXPCContext()->GetAppropriateSecurityManager(
205
nsIXPCSecurityManager::HOOK_CREATE_INSTANCE);
207
NS_SUCCEEDED(sm->CanCreateInstance(ccx, cid));
212
JS_ClearPendingException(ccx);
213
*classExists = PR_TRUE;
216
*classExists = ClassExists(clsid);
218
// Test the Internet Explorer black list
219
const TCHAR kIEControlsBlacklist[] = _T("SOFTWARE\\Microsoft\\Internet Explorer\\ActiveX Compatibility");
221
if(keyExplorer.Open(HKEY_LOCAL_MACHINE,
222
kIEControlsBlacklist, KEY_READ) == ERROR_SUCCESS)
224
LPOLESTR szCLSID = NULL;
225
::StringFromCLSID(clsid, &szCLSID);
230
if(keyCLSID.Open(keyExplorer, W2T(szCLSID), KEY_READ) == ERROR_SUCCESS)
232
DWORD dwType = REG_DWORD;
234
DWORD dwBufSize = sizeof(dwFlags);
235
if(::RegQueryValueEx(keyCLSID, _T("Compatibility Flags"),
236
NULL, &dwType, (LPBYTE) &dwFlags, &dwBufSize) == ERROR_SUCCESS)
238
// Documented flags for this reg key
239
const DWORD kKillBit = 0x00000400; // MS Knowledge Base 240797
240
if(dwFlags & kKillBit)
242
::CoTaskMemFree(szCLSID);
248
::CoTaskMemFree(szCLSID);
256
/* boolean isClassMarkedSafeForScripting (in nsCIDRef clsid, out boolean classExists); */
257
NS_IMETHODIMP nsDispatchSupport::IsClassMarkedSafeForScripting(const nsCID & cid, PRBool *classExists, PRBool *aResult)
259
NS_ENSURE_ARG_POINTER(aResult);
260
NS_ENSURE_ARG_POINTER(classExists);
261
// Test the category the object belongs to
262
CLSID clsid = XPCDispnsCID2CLSID(cid);
263
*aResult = ClassImplementsCategory(clsid, CATID_SafeForScripting, *classExists);
267
/* boolean isObjectSafeForScripting (in voidPtr theObject, in nsIIDRef iid); */
268
NS_IMETHODIMP nsDispatchSupport::IsObjectSafeForScripting(void * theObject, const nsIID & id, PRBool *aResult)
270
NS_ENSURE_ARG_POINTER(theObject);
271
NS_ENSURE_ARG_POINTER(aResult);
273
// Test if the object implements IObjectSafety and is marked safe for scripting
274
IUnknown *pObject = (IUnknown *) theObject;
275
IID iid = XPCDispIID2IID(id);
277
// Ask the control if its safe for scripting
278
CComQIPtr<IObjectSafety> objectSafety = pObject;
285
DWORD dwSupported = 0; // Supported options (mask)
286
DWORD dwEnabled = 0; // Enabled options
288
// Assume scripting via IDispatch
289
if(FAILED(objectSafety->GetInterfaceSafetyOptions(
290
iid, &dwSupported, &dwEnabled)))
292
// Interface is not safe or failure.
297
// Test if safe for scripting
298
if(!(dwEnabled & dwSupported) & INTERFACESAFE_FOR_UNTRUSTED_CALLER)
300
// Object says it is not set to be safe, but supports unsafe calling,
301
// try enabling it and asking again.
303
if(!(dwSupported & INTERFACESAFE_FOR_UNTRUSTED_CALLER) ||
304
FAILED(objectSafety->SetInterfaceSafetyOptions(
305
iid, INTERFACESAFE_FOR_UNTRUSTED_CALLER, INTERFACESAFE_FOR_UNTRUSTED_CALLER)) ||
306
FAILED(objectSafety->GetInterfaceSafetyOptions(
307
iid, &dwSupported, &dwEnabled)) ||
308
!(dwEnabled & dwSupported) & INTERFACESAFE_FOR_UNTRUSTED_CALLER)
319
static const PRUint32 kDefaultHostingFlags =
320
nsIActiveXSecurityPolicy::HOSTING_FLAGS_HOST_NOTHING;
322
/* unsigned long getHostingFlags (in string aContext); */
323
NS_IMETHODIMP nsDispatchSupport::GetHostingFlags(const char *aContext, PRUint32 *aResult)
325
NS_ENSURE_ARG_POINTER(aResult);
327
// Ask the activex security policy what the hosting flags are
329
nsCOMPtr<nsIActiveXSecurityPolicy> securityPolicy =
330
do_GetService(NS_IACTIVEXSECURITYPOLICY_CONTRACTID, &rv);
331
if(NS_SUCCEEDED(rv) && securityPolicy)
332
return securityPolicy->GetHostingFlags(aContext, aResult);
334
// No policy so use the defaults
335
*aResult = kDefaultHostingFlags;
339
nsDispatchSupport* nsDispatchSupport::GetSingleton()
343
mInstance = new nsDispatchSupport;
344
NS_IF_ADDREF(mInstance);
346
NS_IF_ADDREF(mInstance);