Source code of Windows XP (NT5)
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 
 
 

719 lines
15 KiB

/*++
Copyright (C) 1996-1999 Microsoft Corporation
Module Name:
ctrldll.cpp
Abstract:
DLL methods, class factory.
--*/
#define INITGUIDS
#define DEFINE_GLOBALS
#include <assert.h>
#include "polyline.h"
#include <servprov.h>
#include <exdisp.h>
#include <shlguid.h>
#include <urlmon.h>
#include "smonctrl.h" // For version numbers
#include "genprop.h"
#include "ctrprop.h"
#include "grphprop.h"
#include "srcprop.h"
#include "appearprop.h"
#include "unihelpr.h"
#include "unkhlpr.h"
#include "appmema.h"
ITypeLib *g_pITypeLib;
DWORD g_dwScriptPolicy = URLPOLICY_ALLOW;
BOOL DLLAttach ( HINSTANCE );
VOID DLLDetach ( VOID );
extern HWND CreateFosterWnd( VOID );
BOOL WINAPI
DllMain (
IN HINSTANCE hInstance,
IN ULONG ulReason,
IN LPVOID // pvReserved
)
/*++
Routine Description:
DllMain is the main entrypoint of the DLL. On a process attach, it calls
the DLL initialization routine. On process detach, it calls the clean up
routine.
Arguments:
hInstance - DLL instance handle
ulReason - Calling reason (DLL_PROCESS_ATTCH, DLL_PROCESS_DETACH, etc.)
pvReserved - Not used
Return Value:
Boolean result - TRUE = success, FALSE = failure
--*/
{
switch (ulReason)
{
case DLL_PROCESS_ATTACH:
return DLLAttach(hInstance);
case DLL_PROCESS_DETACH:
DLLDetach();
return TRUE;
default:
return TRUE;
}
}
BOOL
DLLAttach (
IN HINSTANCE hInst
)
/*++
Routine Description:
DLLAttach initializes global variables and objects, and loads the type library.
It saves the DLL instance handle in global variable, g_hInstance.
Arguments:
hInst - DLL instance handle
Return Value:
Boolean status - TRUE = success
--*/
{
HRESULT hr;
USES_CONVERSION
g_hInstance = hInst;
// Initialize general purpose critical section
InitializeCriticalSection(&g_CriticalSection);
// Create foster window
g_hWndFoster = CreateFosterWnd();
if (g_hWndFoster == NULL)
return FALSE;
//assert( IsWindowUnicode( g_hwndFoster ) );
// Try loading type library from registry info
hr = LoadRegTypeLib(LIBID_SystemMonitor, SMONCTRL_MAJ_VERSION, SMONCTRL_MIN_VERSION
, LANG_NEUTRAL, &g_pITypeLib);
// If failed, try loading our typelib resource
if (FAILED(hr)) {
TCHAR szModule[MAX_PATH];
PWCHAR pszTest;
GetModuleFileName(g_hInstance, szModule, MAX_PATH);
pszTest = T2W(szModule);
hr = LoadTypeLib(pszTest, &g_pITypeLib);
}
// Initialize the perf counters
AppPerfOpen(hInst);
if (FAILED(hr))
return FALSE;
return TRUE;
}
VOID
DLLDetach (
VOID
)
/*++
Routine Description:
This routine deletes global variables and objects and unregisters
all of the window classes.
Arguments:
None.
Return Value:
None.
--*/
{
INT i;
// Delete the foster window
if (g_hWndFoster)
DestroyWindow(g_hWndFoster);
// Unregister all window classes
for (i=0; i<MAX_WINDOW_CLASSES; i++) {
if (pstrRegisteredClasses[i] != NULL) {
UnregisterClass(pstrRegisteredClasses[i], g_hInstance);
}
}
// Release the typelib
if (g_pITypeLib != NULL)
g_pITypeLib->Release();
AppPerfClose ((HINSTANCE)NULL);
}
/*
* DllGetClassObject
*
* Purpose:
* Provides an IClassFactory for a given CLSID that this DLL is
* registered to support. This DLL is placed under the CLSID
* in the registration database as the InProcServer.
*
* Parameters:
* clsID REFCLSID that identifies the class factory
* desired. Since this parameter is passed this
* DLL can handle any number of objects simply
* by returning different class factories here
* for different CLSIDs.
*
* riid REFIID specifying the interface the caller wants
* on the class object, usually IID_ClassFactory.
*
* ppv PPVOID in which to return the interface
* pointer.
*
* Return Value:
* HRESULT NOERROR on success, otherwise an error code.
*/
HRESULT APIENTRY
DllGetClassObject (
IN REFCLSID rclsid,
IN REFIID riid,
OUT PPVOID ppv
)
/*++
Routine Description:
DllGetClassObject creates a class factory for the specified object class.
The routine handles the primary control and the property pages.
Arguments:
rclsid - CLSID of object
riid - IID of requested interface (IID_IUNknown or IID_IClassFactory)
ppv - Pointer to returned interface pointer
Return Value:
HRESULT
--*/
{
// Check for valid interface request
if (IID_IUnknown != riid && IID_IClassFactory != riid)
return ResultFromScode(E_NOINTERFACE);
// Create class factory for request class
if (CLSID_SystemMonitor == rclsid)
*ppv = new CPolylineClassFactory;
else if (CLSID_GeneralPropPage == rclsid)
*ppv = new CSysmonPropPageFactory(GENERAL_PROPPAGE);
else if (CLSID_SourcePropPage == rclsid)
*ppv = new CSysmonPropPageFactory(SOURCE_PROPPAGE);
else if (CLSID_CounterPropPage == rclsid)
*ppv = new CSysmonPropPageFactory(COUNTER_PROPPAGE);
else if (CLSID_GraphPropPage == rclsid)
*ppv = new CSysmonPropPageFactory(GRAPH_PROPPAGE);
else if (CLSID_AppearPropPage == rclsid)
*ppv = new CSysmonPropPageFactory(APPEAR_PROPPAGE);
else
return ResultFromScode(E_FAIL);
if (NULL == *ppv)
return ResultFromScode(E_OUTOFMEMORY);
// AddRef the class factory object
((LPUNKNOWN)*ppv)->AddRef();
return NOERROR;
}
STDAPI
DllCanUnloadNow (
VOID
)
/*++
Routine Description:
DllCanUnload determines whether the DLL can be unloaded now. The DLL must
remain active if any objects exist or any class factories are locked.
Arguments:
None.
Return Value:
HRESULT - S_OK if OK to unload, S_FALSE if not
--*/
{
SCODE sc;
// OK to unload if no locks or objects
sc = (0L == g_cObj && 0L == g_cLock) ? S_OK : S_FALSE;
return ResultFromScode(sc);
}
VOID
ObjectDestroyed (
VOID
)
/*++
Routine Description:
ObjectDestroyed decrements the global object count. It is called whenever
an object is destroyed. The count controls the lifetme of the DLL.
Arguments:
None.
Return Value:
None.
--*/
{
InterlockedDecrement(&g_cObj);
}
//---------------------------------------------------------------------------
// Class factory constructor & destructor
//---------------------------------------------------------------------------
/*
* CPolylineClassFactory::CPolylineClassFactory
*
* Purpose:
* Constructor for an object supporting an IClassFactory that
* instantiates Polyline objects.
*
* Parameters:
* None
*/
CPolylineClassFactory::CPolylineClassFactory (
VOID
)
{
m_cRef = 0L;
}
/*
* CPolylineClassFactory::~CPolylineClassFactory
*
* Purpose:
* Destructor for a CPolylineClassFactory object. This will be
* called when we Release the object to a zero reference count.
*/
CPolylineClassFactory::~CPolylineClassFactory (
VOID
)
{
return;
}
//---------------------------------------------------------------------------
// Standard IUnknown implementation for class factory
//---------------------------------------------------------------------------
STDMETHODIMP
CPolylineClassFactory::QueryInterface (
IN REFIID riid,
OUT PPVOID ppv
)
{
*ppv = NULL;
if (IID_IUnknown == riid || IID_IClassFactory == riid)
*ppv=this;
if (NULL != *ppv)
{
((LPUNKNOWN)*ppv)->AddRef();
return NOERROR;
}
return ResultFromScode(E_NOINTERFACE);
}
STDMETHODIMP_(ULONG)
CPolylineClassFactory::AddRef (
VOID
)
{
return ++m_cRef;
}
STDMETHODIMP_(ULONG)
CPolylineClassFactory::Release (
VOID
)
{
if (0L != --m_cRef)
return m_cRef;
delete this;
return 0L;
}
STDMETHODIMP
CPolylineClassFactory::CreateInstance (
IN LPUNKNOWN pUnkOuter,
IN REFIID riid,
OUT PPVOID ppvObj
)
/*++
Routine Description:
CreateInstance creates an instance of the control object and returns
the requested interface to it.
Arguments:
pUnkOuter - IUnknown of outer controling object
riid - IID of requested object interface
ppvObj - Pointer to returned interface pointer
Return Value:
HRESULT - NOERROR, E_NOINTERFACE, or E_OUTOFMEMORY
--*/
{
PCPolyline pObj;
HRESULT hr;
*ppvObj = NULL;
hr = ResultFromScode(E_OUTOFMEMORY);
// Verify that a controlling unknown asks for IUnknown
if (NULL != pUnkOuter && IID_IUnknown != riid)
return ResultFromScode(E_NOINTERFACE);
// Create the object instance
pObj = new CPolyline(pUnkOuter, ObjectDestroyed);
if (NULL == pObj)
return hr;
// Initialize and get the requested interface
if (pObj->Init())
hr = pObj->QueryInterface(riid, ppvObj);
// Delete object if initialization failed
// Otherwise increment gloabl object count
if (FAILED(hr))
delete pObj;
else
InterlockedIncrement(&g_cObj);
return hr;
}
STDMETHODIMP
CPolylineClassFactory::LockServer (
IN BOOL fLock
)
/*++
Routine Description:
LockServer increments or decrements the DLL lock count. A non-zero lock
count prevents the DLL from unloading.
Arguments:
fLock - Lock operation (TRUE = increment, FALSE = decrement)
Return Value:
HRESULT - Always NOERROR
--*/
{
if (fLock)
InterlockedIncrement(&g_cLock);
else
InterlockedDecrement(&g_cLock);
return NOERROR;
}
//
// CImpIObjectSafety interface implmentation
//
IMPLEMENT_CONTAINED_IUNKNOWN(CImpIObjectSafety);
CImpIObjectSafety::CImpIObjectSafety(PCPolyline pObj, LPUNKNOWN pUnkOuter)
:
m_cRef(0),
m_pObj(pObj),
m_pUnkOuter(pUnkOuter),
m_fMessageDisplayed(FALSE)
{
}
CImpIObjectSafety::~CImpIObjectSafety()
{
}
STDMETHODIMP
CImpIObjectSafety::GetInterfaceSafetyOptions(
REFIID riid,
DWORD *pdwSupportedOptions,
DWORD *pdwEnabledOptions
)
/*++
Routine Description:
Retrieve the safety capability of object
Arguments:
riid - Interface ID to retrieve
pdwSupportedOptions - The options the object knows about(might not support)
pdwEnabledOptions - The options the object supports
Return Value:
HRESULT
--*/
{
HRESULT hr = S_OK;
if (pdwSupportedOptions == NULL || pdwEnabledOptions == NULL) {
return E_POINTER;
}
if (riid == IID_IDispatch) {
//
// Safe for scripting
//
*pdwSupportedOptions = INTERFACESAFE_FOR_UNTRUSTED_CALLER;
*pdwEnabledOptions = INTERFACESAFE_FOR_UNTRUSTED_CALLER;
}
else if (riid == IID_IPersistPropertyBag || riid == IID_IPersistStreamInit) {
//
// Safety for initializing
//
*pdwSupportedOptions = INTERFACESAFE_FOR_UNTRUSTED_DATA;
*pdwEnabledOptions = INTERFACESAFE_FOR_UNTRUSTED_DATA;
}
else {
//
// We don't support interfaces, fail out
//
*pdwSupportedOptions = 0;
*pdwEnabledOptions = 0;
hr = E_NOINTERFACE;
}
return hr;
}
STDMETHODIMP
CImpIObjectSafety::SetInterfaceSafetyOptions(
REFIID riid,
DWORD dwOptionSetMask,
DWORD dwEnabledOptions
)
/*++
Routine Description:
The function is used for container to ask an object if it is safe
for scripting or safe for initialization
Arguments:
riid - Interface ID to query
dwSupportedOptions - The options the object knows about(might not support)
dwEnabledOptions - The options the object supports
Return Value:
HRESULT
--*/
{
//
// If we're being asked to set our safe for scripting or
// safe for initialization options then oblige
//
if (0 == dwOptionSetMask && 0 == dwEnabledOptions)
{
//
// the control certainly supports NO requests through the specified interface
// so it's safe to return S_OK even if the interface isn't supported.
//
return S_OK;
}
SetupSecurityPolicy();
if (riid == IID_IDispatch)
{
//
// Client is asking if it is safe to call through IDispatch
//
if (INTERFACESAFE_FOR_UNTRUSTED_CALLER == dwOptionSetMask &&
INTERFACESAFE_FOR_UNTRUSTED_CALLER == dwEnabledOptions)
{
return S_OK;
}
}
else if (riid == IID_IPersistPropertyBag || riid == IID_IPersistStreamInit)
{
//
// Client is asking if it's safe to call through IPersistXXX
//
if (INTERFACESAFE_FOR_UNTRUSTED_DATA == dwOptionSetMask &&
INTERFACESAFE_FOR_UNTRUSTED_DATA == dwEnabledOptions)
{
return S_OK;
}
}
return E_FAIL;
}
VOID
CImpIObjectSafety::SetupSecurityPolicy()
/*++
Routine Description:
The function check if we are safe for scripting.
Arguments:
None
Return Value:
Return TRUE if we are safe for scripting, othewise return FALSE
--*/
{
HRESULT hr;
IServiceProvider* pSrvProvider = NULL;
IWebBrowser2* pWebBrowser = NULL;
IInternetSecurityManager* pISM = NULL;
BSTR bstrURL;
DWORD dwContext = 0;
g_dwScriptPolicy = URLPOLICY_ALLOW;
//
// Get the service provider
//
hr = m_pObj->m_pIOleClientSite->QueryInterface(IID_IServiceProvider, (void **)&pSrvProvider);
if (SUCCEEDED(hr)) {
hr = pSrvProvider->QueryService(SID_SWebBrowserApp,
IID_IWebBrowser2,
(void **)&pWebBrowser);
}
if (SUCCEEDED(hr)) {
hr = pSrvProvider->QueryService(SID_SInternetSecurityManager,
IID_IInternetSecurityManager,
(void**)&pISM);
}
if (SUCCEEDED(hr)) {
hr = pWebBrowser->get_LocationURL(&bstrURL);
}
//
// Querying safe for scripting
//
if (SUCCEEDED(hr)) {
hr = pISM->ProcessUrlAction(bstrURL,
URLACTION_ACTIVEX_CONFIRM_NOOBJECTSAFETY,
(BYTE*)&g_dwScriptPolicy,
sizeof(g_dwScriptPolicy),
(BYTE*)&dwContext,
sizeof(dwContext),
PUAF_NOUI,
0);
}
if (SUCCEEDED(hr)) {
if (g_dwScriptPolicy == URLPOLICY_QUERY) {
g_dwScriptPolicy = URLPOLICY_ALLOW;
}
}
if (pWebBrowser) {
pWebBrowser->Release();
}
if (pSrvProvider) {
pSrvProvider->Release();
}
if (pISM) {
pISM->Release();
}
}