/*++ Copyright (C) 1996-1999 Microsoft Corporation Module Name: ctrldll.cpp Abstract: DLL methods, class factory. --*/ #define INITGUIDS #define DEFINE_GLOBALS #include #include "polyline.h" #include #include #include #include #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; iRelease(); 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(); } }