|
|
/*++
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(); } }
|