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

  1. /*++
  2. Copyright (C) 1996-1999 Microsoft Corporation
  3. Module Name:
  4. ctrldll.cpp
  5. Abstract:
  6. DLL methods, class factory.
  7. --*/
  8. #define INITGUIDS
  9. #define DEFINE_GLOBALS
  10. #include <assert.h>
  11. #include "polyline.h"
  12. #include <servprov.h>
  13. #include <exdisp.h>
  14. #include <shlguid.h>
  15. #include <urlmon.h>
  16. #include "smonctrl.h" // For version numbers
  17. #include "genprop.h"
  18. #include "ctrprop.h"
  19. #include "grphprop.h"
  20. #include "srcprop.h"
  21. #include "appearprop.h"
  22. #include "unihelpr.h"
  23. #include "unkhlpr.h"
  24. #include "appmema.h"
  25. ITypeLib *g_pITypeLib;
  26. DWORD g_dwScriptPolicy = URLPOLICY_ALLOW;
  27. BOOL DLLAttach ( HINSTANCE );
  28. VOID DLLDetach ( VOID );
  29. extern HWND CreateFosterWnd( VOID );
  30. BOOL WINAPI
  31. DllMain (
  32. IN HINSTANCE hInstance,
  33. IN ULONG ulReason,
  34. IN LPVOID // pvReserved
  35. )
  36. /*++
  37. Routine Description:
  38. DllMain is the main entrypoint of the DLL. On a process attach, it calls
  39. the DLL initialization routine. On process detach, it calls the clean up
  40. routine.
  41. Arguments:
  42. hInstance - DLL instance handle
  43. ulReason - Calling reason (DLL_PROCESS_ATTCH, DLL_PROCESS_DETACH, etc.)
  44. pvReserved - Not used
  45. Return Value:
  46. Boolean result - TRUE = success, FALSE = failure
  47. --*/
  48. {
  49. switch (ulReason)
  50. {
  51. case DLL_PROCESS_ATTACH:
  52. return DLLAttach(hInstance);
  53. case DLL_PROCESS_DETACH:
  54. DLLDetach();
  55. return TRUE;
  56. default:
  57. return TRUE;
  58. }
  59. }
  60. BOOL
  61. DLLAttach (
  62. IN HINSTANCE hInst
  63. )
  64. /*++
  65. Routine Description:
  66. DLLAttach initializes global variables and objects, and loads the type library.
  67. It saves the DLL instance handle in global variable, g_hInstance.
  68. Arguments:
  69. hInst - DLL instance handle
  70. Return Value:
  71. Boolean status - TRUE = success
  72. --*/
  73. {
  74. HRESULT hr;
  75. USES_CONVERSION
  76. g_hInstance = hInst;
  77. // Initialize general purpose critical section
  78. InitializeCriticalSection(&g_CriticalSection);
  79. // Create foster window
  80. g_hWndFoster = CreateFosterWnd();
  81. if (g_hWndFoster == NULL)
  82. return FALSE;
  83. //assert( IsWindowUnicode( g_hwndFoster ) );
  84. // Try loading type library from registry info
  85. hr = LoadRegTypeLib(LIBID_SystemMonitor, SMONCTRL_MAJ_VERSION, SMONCTRL_MIN_VERSION
  86. , LANG_NEUTRAL, &g_pITypeLib);
  87. // If failed, try loading our typelib resource
  88. if (FAILED(hr)) {
  89. TCHAR szModule[MAX_PATH];
  90. PWCHAR pszTest;
  91. GetModuleFileName(g_hInstance, szModule, MAX_PATH);
  92. pszTest = T2W(szModule);
  93. hr = LoadTypeLib(pszTest, &g_pITypeLib);
  94. }
  95. // Initialize the perf counters
  96. AppPerfOpen(hInst);
  97. if (FAILED(hr))
  98. return FALSE;
  99. return TRUE;
  100. }
  101. VOID
  102. DLLDetach (
  103. VOID
  104. )
  105. /*++
  106. Routine Description:
  107. This routine deletes global variables and objects and unregisters
  108. all of the window classes.
  109. Arguments:
  110. None.
  111. Return Value:
  112. None.
  113. --*/
  114. {
  115. INT i;
  116. // Delete the foster window
  117. if (g_hWndFoster)
  118. DestroyWindow(g_hWndFoster);
  119. // Unregister all window classes
  120. for (i=0; i<MAX_WINDOW_CLASSES; i++) {
  121. if (pstrRegisteredClasses[i] != NULL) {
  122. UnregisterClass(pstrRegisteredClasses[i], g_hInstance);
  123. }
  124. }
  125. // Release the typelib
  126. if (g_pITypeLib != NULL)
  127. g_pITypeLib->Release();
  128. AppPerfClose ((HINSTANCE)NULL);
  129. }
  130. /*
  131. * DllGetClassObject
  132. *
  133. * Purpose:
  134. * Provides an IClassFactory for a given CLSID that this DLL is
  135. * registered to support. This DLL is placed under the CLSID
  136. * in the registration database as the InProcServer.
  137. *
  138. * Parameters:
  139. * clsID REFCLSID that identifies the class factory
  140. * desired. Since this parameter is passed this
  141. * DLL can handle any number of objects simply
  142. * by returning different class factories here
  143. * for different CLSIDs.
  144. *
  145. * riid REFIID specifying the interface the caller wants
  146. * on the class object, usually IID_ClassFactory.
  147. *
  148. * ppv PPVOID in which to return the interface
  149. * pointer.
  150. *
  151. * Return Value:
  152. * HRESULT NOERROR on success, otherwise an error code.
  153. */
  154. HRESULT APIENTRY
  155. DllGetClassObject (
  156. IN REFCLSID rclsid,
  157. IN REFIID riid,
  158. OUT PPVOID ppv
  159. )
  160. /*++
  161. Routine Description:
  162. DllGetClassObject creates a class factory for the specified object class.
  163. The routine handles the primary control and the property pages.
  164. Arguments:
  165. rclsid - CLSID of object
  166. riid - IID of requested interface (IID_IUNknown or IID_IClassFactory)
  167. ppv - Pointer to returned interface pointer
  168. Return Value:
  169. HRESULT
  170. --*/
  171. {
  172. // Check for valid interface request
  173. if (IID_IUnknown != riid && IID_IClassFactory != riid)
  174. return ResultFromScode(E_NOINTERFACE);
  175. // Create class factory for request class
  176. if (CLSID_SystemMonitor == rclsid)
  177. *ppv = new CPolylineClassFactory;
  178. else if (CLSID_GeneralPropPage == rclsid)
  179. *ppv = new CSysmonPropPageFactory(GENERAL_PROPPAGE);
  180. else if (CLSID_SourcePropPage == rclsid)
  181. *ppv = new CSysmonPropPageFactory(SOURCE_PROPPAGE);
  182. else if (CLSID_CounterPropPage == rclsid)
  183. *ppv = new CSysmonPropPageFactory(COUNTER_PROPPAGE);
  184. else if (CLSID_GraphPropPage == rclsid)
  185. *ppv = new CSysmonPropPageFactory(GRAPH_PROPPAGE);
  186. else if (CLSID_AppearPropPage == rclsid)
  187. *ppv = new CSysmonPropPageFactory(APPEAR_PROPPAGE);
  188. else
  189. return ResultFromScode(E_FAIL);
  190. if (NULL == *ppv)
  191. return ResultFromScode(E_OUTOFMEMORY);
  192. // AddRef the class factory object
  193. ((LPUNKNOWN)*ppv)->AddRef();
  194. return NOERROR;
  195. }
  196. STDAPI
  197. DllCanUnloadNow (
  198. VOID
  199. )
  200. /*++
  201. Routine Description:
  202. DllCanUnload determines whether the DLL can be unloaded now. The DLL must
  203. remain active if any objects exist or any class factories are locked.
  204. Arguments:
  205. None.
  206. Return Value:
  207. HRESULT - S_OK if OK to unload, S_FALSE if not
  208. --*/
  209. {
  210. SCODE sc;
  211. // OK to unload if no locks or objects
  212. sc = (0L == g_cObj && 0L == g_cLock) ? S_OK : S_FALSE;
  213. return ResultFromScode(sc);
  214. }
  215. VOID
  216. ObjectDestroyed (
  217. VOID
  218. )
  219. /*++
  220. Routine Description:
  221. ObjectDestroyed decrements the global object count. It is called whenever
  222. an object is destroyed. The count controls the lifetme of the DLL.
  223. Arguments:
  224. None.
  225. Return Value:
  226. None.
  227. --*/
  228. {
  229. InterlockedDecrement(&g_cObj);
  230. }
  231. //---------------------------------------------------------------------------
  232. // Class factory constructor & destructor
  233. //---------------------------------------------------------------------------
  234. /*
  235. * CPolylineClassFactory::CPolylineClassFactory
  236. *
  237. * Purpose:
  238. * Constructor for an object supporting an IClassFactory that
  239. * instantiates Polyline objects.
  240. *
  241. * Parameters:
  242. * None
  243. */
  244. CPolylineClassFactory::CPolylineClassFactory (
  245. VOID
  246. )
  247. {
  248. m_cRef = 0L;
  249. }
  250. /*
  251. * CPolylineClassFactory::~CPolylineClassFactory
  252. *
  253. * Purpose:
  254. * Destructor for a CPolylineClassFactory object. This will be
  255. * called when we Release the object to a zero reference count.
  256. */
  257. CPolylineClassFactory::~CPolylineClassFactory (
  258. VOID
  259. )
  260. {
  261. return;
  262. }
  263. //---------------------------------------------------------------------------
  264. // Standard IUnknown implementation for class factory
  265. //---------------------------------------------------------------------------
  266. STDMETHODIMP
  267. CPolylineClassFactory::QueryInterface (
  268. IN REFIID riid,
  269. OUT PPVOID ppv
  270. )
  271. {
  272. *ppv = NULL;
  273. if (IID_IUnknown == riid || IID_IClassFactory == riid)
  274. *ppv=this;
  275. if (NULL != *ppv)
  276. {
  277. ((LPUNKNOWN)*ppv)->AddRef();
  278. return NOERROR;
  279. }
  280. return ResultFromScode(E_NOINTERFACE);
  281. }
  282. STDMETHODIMP_(ULONG)
  283. CPolylineClassFactory::AddRef (
  284. VOID
  285. )
  286. {
  287. return ++m_cRef;
  288. }
  289. STDMETHODIMP_(ULONG)
  290. CPolylineClassFactory::Release (
  291. VOID
  292. )
  293. {
  294. if (0L != --m_cRef)
  295. return m_cRef;
  296. delete this;
  297. return 0L;
  298. }
  299. STDMETHODIMP
  300. CPolylineClassFactory::CreateInstance (
  301. IN LPUNKNOWN pUnkOuter,
  302. IN REFIID riid,
  303. OUT PPVOID ppvObj
  304. )
  305. /*++
  306. Routine Description:
  307. CreateInstance creates an instance of the control object and returns
  308. the requested interface to it.
  309. Arguments:
  310. pUnkOuter - IUnknown of outer controling object
  311. riid - IID of requested object interface
  312. ppvObj - Pointer to returned interface pointer
  313. Return Value:
  314. HRESULT - NOERROR, E_NOINTERFACE, or E_OUTOFMEMORY
  315. --*/
  316. {
  317. PCPolyline pObj;
  318. HRESULT hr;
  319. *ppvObj = NULL;
  320. hr = ResultFromScode(E_OUTOFMEMORY);
  321. // Verify that a controlling unknown asks for IUnknown
  322. if (NULL != pUnkOuter && IID_IUnknown != riid)
  323. return ResultFromScode(E_NOINTERFACE);
  324. // Create the object instance
  325. pObj = new CPolyline(pUnkOuter, ObjectDestroyed);
  326. if (NULL == pObj)
  327. return hr;
  328. // Initialize and get the requested interface
  329. if (pObj->Init())
  330. hr = pObj->QueryInterface(riid, ppvObj);
  331. // Delete object if initialization failed
  332. // Otherwise increment gloabl object count
  333. if (FAILED(hr))
  334. delete pObj;
  335. else
  336. InterlockedIncrement(&g_cObj);
  337. return hr;
  338. }
  339. STDMETHODIMP
  340. CPolylineClassFactory::LockServer (
  341. IN BOOL fLock
  342. )
  343. /*++
  344. Routine Description:
  345. LockServer increments or decrements the DLL lock count. A non-zero lock
  346. count prevents the DLL from unloading.
  347. Arguments:
  348. fLock - Lock operation (TRUE = increment, FALSE = decrement)
  349. Return Value:
  350. HRESULT - Always NOERROR
  351. --*/
  352. {
  353. if (fLock)
  354. InterlockedIncrement(&g_cLock);
  355. else
  356. InterlockedDecrement(&g_cLock);
  357. return NOERROR;
  358. }
  359. //
  360. // CImpIObjectSafety interface implmentation
  361. //
  362. IMPLEMENT_CONTAINED_IUNKNOWN(CImpIObjectSafety);
  363. CImpIObjectSafety::CImpIObjectSafety(PCPolyline pObj, LPUNKNOWN pUnkOuter)
  364. :
  365. m_cRef(0),
  366. m_pObj(pObj),
  367. m_pUnkOuter(pUnkOuter),
  368. m_fMessageDisplayed(FALSE)
  369. {
  370. }
  371. CImpIObjectSafety::~CImpIObjectSafety()
  372. {
  373. }
  374. STDMETHODIMP
  375. CImpIObjectSafety::GetInterfaceSafetyOptions(
  376. REFIID riid,
  377. DWORD *pdwSupportedOptions,
  378. DWORD *pdwEnabledOptions
  379. )
  380. /*++
  381. Routine Description:
  382. Retrieve the safety capability of object
  383. Arguments:
  384. riid - Interface ID to retrieve
  385. pdwSupportedOptions - The options the object knows about(might not support)
  386. pdwEnabledOptions - The options the object supports
  387. Return Value:
  388. HRESULT
  389. --*/
  390. {
  391. HRESULT hr = S_OK;
  392. if (pdwSupportedOptions == NULL || pdwEnabledOptions == NULL) {
  393. return E_POINTER;
  394. }
  395. if (riid == IID_IDispatch) {
  396. //
  397. // Safe for scripting
  398. //
  399. *pdwSupportedOptions = INTERFACESAFE_FOR_UNTRUSTED_CALLER;
  400. *pdwEnabledOptions = INTERFACESAFE_FOR_UNTRUSTED_CALLER;
  401. }
  402. else if (riid == IID_IPersistPropertyBag || riid == IID_IPersistStreamInit) {
  403. //
  404. // Safety for initializing
  405. //
  406. *pdwSupportedOptions = INTERFACESAFE_FOR_UNTRUSTED_DATA;
  407. *pdwEnabledOptions = INTERFACESAFE_FOR_UNTRUSTED_DATA;
  408. }
  409. else {
  410. //
  411. // We don't support interfaces, fail out
  412. //
  413. *pdwSupportedOptions = 0;
  414. *pdwEnabledOptions = 0;
  415. hr = E_NOINTERFACE;
  416. }
  417. return hr;
  418. }
  419. STDMETHODIMP
  420. CImpIObjectSafety::SetInterfaceSafetyOptions(
  421. REFIID riid,
  422. DWORD dwOptionSetMask,
  423. DWORD dwEnabledOptions
  424. )
  425. /*++
  426. Routine Description:
  427. The function is used for container to ask an object if it is safe
  428. for scripting or safe for initialization
  429. Arguments:
  430. riid - Interface ID to query
  431. dwSupportedOptions - The options the object knows about(might not support)
  432. dwEnabledOptions - The options the object supports
  433. Return Value:
  434. HRESULT
  435. --*/
  436. {
  437. //
  438. // If we're being asked to set our safe for scripting or
  439. // safe for initialization options then oblige
  440. //
  441. if (0 == dwOptionSetMask && 0 == dwEnabledOptions)
  442. {
  443. //
  444. // the control certainly supports NO requests through the specified interface
  445. // so it's safe to return S_OK even if the interface isn't supported.
  446. //
  447. return S_OK;
  448. }
  449. SetupSecurityPolicy();
  450. if (riid == IID_IDispatch)
  451. {
  452. //
  453. // Client is asking if it is safe to call through IDispatch
  454. //
  455. if (INTERFACESAFE_FOR_UNTRUSTED_CALLER == dwOptionSetMask &&
  456. INTERFACESAFE_FOR_UNTRUSTED_CALLER == dwEnabledOptions)
  457. {
  458. return S_OK;
  459. }
  460. }
  461. else if (riid == IID_IPersistPropertyBag || riid == IID_IPersistStreamInit)
  462. {
  463. //
  464. // Client is asking if it's safe to call through IPersistXXX
  465. //
  466. if (INTERFACESAFE_FOR_UNTRUSTED_DATA == dwOptionSetMask &&
  467. INTERFACESAFE_FOR_UNTRUSTED_DATA == dwEnabledOptions)
  468. {
  469. return S_OK;
  470. }
  471. }
  472. return E_FAIL;
  473. }
  474. VOID
  475. CImpIObjectSafety::SetupSecurityPolicy()
  476. /*++
  477. Routine Description:
  478. The function check if we are safe for scripting.
  479. Arguments:
  480. None
  481. Return Value:
  482. Return TRUE if we are safe for scripting, othewise return FALSE
  483. --*/
  484. {
  485. HRESULT hr;
  486. IServiceProvider* pSrvProvider = NULL;
  487. IWebBrowser2* pWebBrowser = NULL;
  488. IInternetSecurityManager* pISM = NULL;
  489. BSTR bstrURL;
  490. DWORD dwContext = 0;
  491. g_dwScriptPolicy = URLPOLICY_ALLOW;
  492. //
  493. // Get the service provider
  494. //
  495. hr = m_pObj->m_pIOleClientSite->QueryInterface(IID_IServiceProvider, (void **)&pSrvProvider);
  496. if (SUCCEEDED(hr)) {
  497. hr = pSrvProvider->QueryService(SID_SWebBrowserApp,
  498. IID_IWebBrowser2,
  499. (void **)&pWebBrowser);
  500. }
  501. if (SUCCEEDED(hr)) {
  502. hr = pSrvProvider->QueryService(SID_SInternetSecurityManager,
  503. IID_IInternetSecurityManager,
  504. (void**)&pISM);
  505. }
  506. if (SUCCEEDED(hr)) {
  507. hr = pWebBrowser->get_LocationURL(&bstrURL);
  508. }
  509. //
  510. // Querying safe for scripting
  511. //
  512. if (SUCCEEDED(hr)) {
  513. hr = pISM->ProcessUrlAction(bstrURL,
  514. URLACTION_ACTIVEX_CONFIRM_NOOBJECTSAFETY,
  515. (BYTE*)&g_dwScriptPolicy,
  516. sizeof(g_dwScriptPolicy),
  517. (BYTE*)&dwContext,
  518. sizeof(dwContext),
  519. PUAF_NOUI,
  520. 0);
  521. }
  522. if (SUCCEEDED(hr)) {
  523. if (g_dwScriptPolicy == URLPOLICY_QUERY) {
  524. g_dwScriptPolicy = URLPOLICY_ALLOW;
  525. }
  526. }
  527. if (pWebBrowser) {
  528. pWebBrowser->Release();
  529. }
  530. if (pSrvProvider) {
  531. pSrvProvider->Release();
  532. }
  533. if (pISM) {
  534. pISM->Release();
  535. }
  536. }