Leaked source code of windows server 2003
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.

871 lines
18 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 "polyline.h"
  11. #include <servprov.h>
  12. #include <exdisp.h>
  13. #include <shlguid.h>
  14. #include <urlmon.h>
  15. #include "smonctrl.h" // For version numbers
  16. #include "genprop.h"
  17. #include "ctrprop.h"
  18. #include "grphprop.h"
  19. #include "srcprop.h"
  20. #include "appearprop.h"
  21. #include "unihelpr.h"
  22. #include "unkhlpr.h"
  23. #include "appmema.h"
  24. #include "globals.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. BOOL fReturn = TRUE;
  50. switch (ulReason)
  51. {
  52. case DLL_PROCESS_ATTACH:
  53. fReturn = DLLAttach(hInstance);
  54. break;
  55. case DLL_PROCESS_DETACH:
  56. DLLDetach();
  57. break;
  58. default:
  59. break;
  60. }
  61. return fReturn;
  62. }
  63. BOOL
  64. DLLAttach (
  65. IN HINSTANCE hInst
  66. )
  67. /*++
  68. Routine Description:
  69. DLLAttach initializes global variables and objects, and loads the type library.
  70. It saves the DLL instance handle in global variable, g_hInstance.
  71. Arguments:
  72. hInst - DLL instance handle
  73. Return Value:
  74. Boolean status - TRUE = success
  75. --*/
  76. {
  77. HRESULT hr = S_OK;
  78. g_hInstance = hInst;
  79. //
  80. // Initialize general purpose critical section
  81. //
  82. try {
  83. InitializeCriticalSection(&g_CriticalSection);
  84. } catch (...) {
  85. hr = E_OUTOFMEMORY;
  86. }
  87. if (!SUCCEEDED(hr)) {
  88. return FALSE;
  89. }
  90. //
  91. // Create foster window
  92. //
  93. g_hWndFoster = CreateFosterWnd();
  94. if (g_hWndFoster == NULL) {
  95. return FALSE;
  96. }
  97. //
  98. // Try loading type library from registry
  99. //
  100. hr = LoadRegTypeLib(LIBID_SystemMonitor,
  101. SMONCTRL_MAJ_VERSION,
  102. SMONCTRL_MIN_VERSION,
  103. LANG_NEUTRAL,
  104. &g_pITypeLib);
  105. //
  106. // If failed, try loading our typelib resource
  107. //
  108. if (FAILED(hr)) {
  109. LPWSTR szModule = NULL;
  110. UINT iModuleLen;
  111. DWORD dwReturn;
  112. int iRetry = 4;
  113. //
  114. // The length initialized to iModuleLen must be longer
  115. // than the length of "%systemroot%\\system32\\sysmon.ocx"
  116. //
  117. iModuleLen = MAX_PATH + 1;
  118. do {
  119. szModule = (LPWSTR) malloc(iModuleLen * sizeof(WCHAR));
  120. if (szModule == NULL) {
  121. hr = E_OUTOFMEMORY;
  122. break;
  123. }
  124. //
  125. // Something wrong, break out
  126. //
  127. dwReturn = GetModuleFileName(g_hInstance, szModule, iModuleLen);
  128. if (dwReturn == 0) {
  129. hr = E_FAIL;
  130. break;
  131. }
  132. //
  133. // The buffer is not big enough, try to allocate a biggers one
  134. // and retry
  135. //
  136. if (dwReturn >= iModuleLen) {
  137. iModuleLen *= 2;
  138. free(szModule);
  139. szModule = NULL;
  140. hr = E_FAIL;
  141. }
  142. else {
  143. hr = S_OK;
  144. break;
  145. }
  146. iRetry --;
  147. } while (iRetry);
  148. if (SUCCEEDED(hr)) {
  149. hr = LoadTypeLib(szModule, &g_pITypeLib);
  150. }
  151. if (szModule) {
  152. free(szModule);
  153. }
  154. }
  155. if (FAILED(hr)) {
  156. return FALSE;
  157. }
  158. //
  159. // Initialize the perf counters
  160. //
  161. AppPerfOpen(hInst);
  162. return TRUE;
  163. }
  164. VOID
  165. DLLDetach (
  166. VOID
  167. )
  168. /*++
  169. Routine Description:
  170. This routine deletes global variables and objects and unregisters
  171. all of the window classes.
  172. Arguments:
  173. None.
  174. Return Value:
  175. None.
  176. --*/
  177. {
  178. INT i;
  179. //
  180. // Delete the foster window
  181. //
  182. if (g_hWndFoster) {
  183. DestroyWindow(g_hWndFoster);
  184. }
  185. //
  186. // Unregister all window classes
  187. //
  188. for (i = 0; i < MAX_WINDOW_CLASSES; i++) {
  189. if (pstrRegisteredClasses[i] != NULL) {
  190. UnregisterClass(pstrRegisteredClasses[i], g_hInstance);
  191. }
  192. }
  193. //
  194. // Release the typelib
  195. //
  196. if (g_pITypeLib != NULL) {
  197. g_pITypeLib->Release();
  198. }
  199. //
  200. // Delete general purpose critical section
  201. //
  202. DeleteCriticalSection(&g_CriticalSection);
  203. AppPerfClose ((HINSTANCE)NULL);
  204. }
  205. /*
  206. * DllGetClassObject
  207. *
  208. * Purpose:
  209. * Provides an IClassFactory for a given CLSID that this DLL is
  210. * registered to support. This DLL is placed under the CLSID
  211. * in the registration database as the InProcServer.
  212. *
  213. * Parameters:
  214. * clsID REFCLSID that identifies the class factory
  215. * desired. Since this parameter is passed this
  216. * DLL can handle any number of objects simply
  217. * by returning different class factories here
  218. * for different CLSIDs.
  219. *
  220. * riid REFIID specifying the interface the caller wants
  221. * on the class object, usually IID_ClassFactory.
  222. *
  223. * ppv PPVOID in which to return the interface
  224. * pointer.
  225. *
  226. * Return Value:
  227. * HRESULT NOERROR on success, otherwise an error code.
  228. */
  229. HRESULT APIENTRY
  230. DllGetClassObject (
  231. IN REFCLSID rclsid,
  232. IN REFIID riid,
  233. OUT PPVOID ppv
  234. )
  235. /*++
  236. Routine Description:
  237. DllGetClassObject creates a class factory for the specified object class.
  238. The routine handles the primary control and the property pages.
  239. Arguments:
  240. rclsid - CLSID of object
  241. riid - IID of requested interface (IID_IUNknown or IID_IClassFactory)
  242. ppv - Pointer to returned interface pointer
  243. Return Value:
  244. HRESULT
  245. --*/
  246. {
  247. HRESULT hr = S_OK;
  248. if (ppv == NULL) {
  249. return E_POINTER;
  250. }
  251. try {
  252. *ppv = NULL;
  253. //
  254. // Check for valid interface request
  255. //
  256. if (IID_IUnknown != riid && IID_IClassFactory != riid) {
  257. hr = E_NOINTERFACE;
  258. }
  259. if (SUCCEEDED(hr)) {
  260. //
  261. // Create class factory for request class
  262. //
  263. if (CLSID_SystemMonitor == rclsid)
  264. *ppv = new CPolylineClassFactory;
  265. else if (CLSID_GeneralPropPage == rclsid)
  266. *ppv = new CSysmonPropPageFactory(GENERAL_PROPPAGE);
  267. else if (CLSID_SourcePropPage == rclsid)
  268. *ppv = new CSysmonPropPageFactory(SOURCE_PROPPAGE);
  269. else if (CLSID_CounterPropPage == rclsid)
  270. *ppv = new CSysmonPropPageFactory(COUNTER_PROPPAGE);
  271. else if (CLSID_GraphPropPage == rclsid)
  272. *ppv = new CSysmonPropPageFactory(GRAPH_PROPPAGE);
  273. else if (CLSID_AppearPropPage == rclsid)
  274. *ppv = new CSysmonPropPageFactory(APPEAR_PROPPAGE);
  275. else
  276. hr = E_NOINTERFACE;
  277. if (*ppv) {
  278. ((LPUNKNOWN)*ppv)->AddRef();
  279. }
  280. else {
  281. hr = E_OUTOFMEMORY;
  282. }
  283. }
  284. } catch (...) {
  285. hr = E_POINTER;
  286. }
  287. return hr;
  288. }
  289. STDAPI
  290. DllCanUnloadNow (
  291. VOID
  292. )
  293. /*++
  294. Routine Description:
  295. DllCanUnload determines whether the DLL can be unloaded now. The DLL must
  296. remain active if any objects exist or any class factories are locked.
  297. Arguments:
  298. None.
  299. Return Value:
  300. HRESULT - S_OK if OK to unload, S_FALSE if not
  301. --*/
  302. {
  303. //
  304. // OK to unload if no locks or objects
  305. //
  306. return (0L == g_cObj && 0L == g_cLock) ? S_OK : S_FALSE;
  307. }
  308. VOID
  309. ObjectDestroyed (
  310. VOID
  311. )
  312. /*++
  313. Routine Description:
  314. ObjectDestroyed decrements the global object count. It is called whenever
  315. an object is destroyed. The count controls the lifetme of the DLL.
  316. Arguments:
  317. None.
  318. Return Value:
  319. None.
  320. --*/
  321. {
  322. InterlockedDecrement(&g_cObj);
  323. }
  324. //---------------------------------------------------------------------------
  325. // Class factory constructor & destructor
  326. //---------------------------------------------------------------------------
  327. /*
  328. * CPolylineClassFactory::CPolylineClassFactory
  329. *
  330. * Purpose:
  331. * Constructor for an object supporting an IClassFactory that
  332. * instantiates Polyline objects.
  333. *
  334. * Parameters:
  335. * None
  336. */
  337. CPolylineClassFactory::CPolylineClassFactory (
  338. VOID
  339. )
  340. {
  341. m_cRef = 0L;
  342. }
  343. /*
  344. * CPolylineClassFactory::~CPolylineClassFactory
  345. *
  346. * Purpose:
  347. * Destructor for a CPolylineClassFactory object. This will be
  348. * called when we Release the object to a zero reference count.
  349. */
  350. CPolylineClassFactory::~CPolylineClassFactory (
  351. VOID
  352. )
  353. {
  354. }
  355. //---------------------------------------------------------------------------
  356. // Standard IUnknown implementation for class factory
  357. //---------------------------------------------------------------------------
  358. STDMETHODIMP
  359. CPolylineClassFactory::QueryInterface (
  360. IN REFIID riid,
  361. OUT PPVOID ppv
  362. )
  363. {
  364. HRESULT hr = S_OK;
  365. if (ppv == NULL) {
  366. return E_POINTER;
  367. }
  368. try {
  369. *ppv = NULL;
  370. if (IID_IUnknown == riid || IID_IClassFactory == riid) {
  371. *ppv = this;
  372. AddRef();
  373. }
  374. else {
  375. hr = E_NOINTERFACE;
  376. }
  377. } catch (...) {
  378. hr = E_POINTER;
  379. }
  380. return hr;
  381. }
  382. STDMETHODIMP_(ULONG)
  383. CPolylineClassFactory::AddRef (
  384. VOID
  385. )
  386. {
  387. return ++m_cRef;
  388. }
  389. STDMETHODIMP_(ULONG)
  390. CPolylineClassFactory::Release (
  391. VOID
  392. )
  393. {
  394. if (0L != --m_cRef)
  395. return m_cRef;
  396. delete this;
  397. return 0L;
  398. }
  399. STDMETHODIMP
  400. CPolylineClassFactory::CreateInstance (
  401. IN LPUNKNOWN pUnkOuter,
  402. IN REFIID riid,
  403. OUT PPVOID ppvObj
  404. )
  405. /*++
  406. Routine Description:
  407. CreateInstance creates an instance of the control object and returns
  408. the requested interface to it.
  409. Arguments:
  410. pUnkOuter - IUnknown of outer controling object
  411. riid - IID of requested object interface
  412. ppvObj - Pointer to returned interface pointer
  413. Return Value:
  414. HRESULT - NOERROR, E_NOINTERFACE, or E_OUTOFMEMORY
  415. --*/
  416. {
  417. PCPolyline pObj;
  418. HRESULT hr = S_OK;
  419. if (ppvObj == NULL) {
  420. return E_POINTER;
  421. }
  422. try {
  423. *ppvObj = NULL;
  424. //
  425. // We use do {} while(0) here to act like a switch statement
  426. //
  427. do {
  428. //
  429. // Verify that a controlling unknown asks for IUnknown
  430. //
  431. if (NULL != pUnkOuter && IID_IUnknown != riid) {
  432. hr = E_NOINTERFACE;
  433. break;
  434. }
  435. //
  436. // Create the object instance
  437. //
  438. pObj = new CPolyline(pUnkOuter, ObjectDestroyed);
  439. if (NULL == pObj) {
  440. hr = E_OUTOFMEMORY;
  441. break;
  442. }
  443. //
  444. // Initialize and get the requested interface
  445. //
  446. if (pObj->Init()) {
  447. hr = pObj->QueryInterface(riid, ppvObj);
  448. }
  449. else {
  450. hr = E_FAIL;
  451. }
  452. //
  453. // Delete object if initialization failed
  454. // Otherwise increment gloabl object count
  455. //
  456. if (FAILED(hr)) {
  457. delete pObj;
  458. }
  459. else {
  460. InterlockedIncrement(&g_cObj);
  461. }
  462. } while (0);
  463. } catch (...) {
  464. hr = E_POINTER;
  465. }
  466. return hr;
  467. }
  468. STDMETHODIMP
  469. CPolylineClassFactory::LockServer (
  470. IN BOOL fLock
  471. )
  472. /*++
  473. Routine Description:
  474. LockServer increments or decrements the DLL lock count. A non-zero lock
  475. count prevents the DLL from unloading.
  476. Arguments:
  477. fLock - Lock operation (TRUE = increment, FALSE = decrement)
  478. Return Value:
  479. HRESULT - Always NOERROR
  480. --*/
  481. {
  482. if (fLock) {
  483. InterlockedIncrement(&g_cLock);
  484. }
  485. else {
  486. InterlockedDecrement(&g_cLock);
  487. }
  488. return S_OK;
  489. }
  490. //
  491. // CImpIObjectSafety interface implmentation
  492. //
  493. IMPLEMENT_CONTAINED_IUNKNOWN(CImpIObjectSafety);
  494. CImpIObjectSafety::CImpIObjectSafety(PCPolyline pObj, LPUNKNOWN pUnkOuter)
  495. :
  496. m_cRef(0),
  497. m_pObj(pObj),
  498. m_pUnkOuter(pUnkOuter),
  499. m_fMessageDisplayed(FALSE)
  500. {
  501. }
  502. CImpIObjectSafety::~CImpIObjectSafety()
  503. {
  504. }
  505. STDMETHODIMP
  506. CImpIObjectSafety::GetInterfaceSafetyOptions(
  507. REFIID riid,
  508. DWORD *pdwSupportedOptions,
  509. DWORD *pdwEnabledOptions
  510. )
  511. /*++
  512. Routine Description:
  513. Retrieve the safety capability of object
  514. Arguments:
  515. riid - Interface ID to retrieve
  516. pdwSupportedOptions - The options the object knows about(might not support)
  517. pdwEnabledOptions - The options the object supports
  518. Return Value:
  519. HRESULT
  520. --*/
  521. {
  522. HRESULT hr = S_OK;
  523. if (pdwSupportedOptions == NULL || pdwEnabledOptions == NULL) {
  524. return E_POINTER;
  525. }
  526. if (riid == IID_IDispatch) {
  527. //
  528. // Safe for scripting
  529. //
  530. *pdwSupportedOptions = INTERFACESAFE_FOR_UNTRUSTED_CALLER;
  531. *pdwEnabledOptions = INTERFACESAFE_FOR_UNTRUSTED_CALLER;
  532. }
  533. else if (riid == IID_IPersistPropertyBag || riid == IID_IPersistStreamInit) {
  534. //
  535. // Safety for initializing
  536. //
  537. *pdwSupportedOptions = INTERFACESAFE_FOR_UNTRUSTED_DATA;
  538. *pdwEnabledOptions = INTERFACESAFE_FOR_UNTRUSTED_DATA;
  539. }
  540. else {
  541. //
  542. // We don't support interfaces, fail out
  543. //
  544. *pdwSupportedOptions = 0;
  545. *pdwEnabledOptions = 0;
  546. hr = E_NOINTERFACE;
  547. }
  548. return hr;
  549. }
  550. STDMETHODIMP
  551. CImpIObjectSafety::SetInterfaceSafetyOptions(
  552. REFIID riid,
  553. DWORD dwOptionSetMask,
  554. DWORD dwEnabledOptions
  555. )
  556. /*++
  557. Routine Description:
  558. The function is used for container to ask an object if it is safe
  559. for scripting or safe for initialization
  560. Arguments:
  561. riid - Interface ID to query
  562. dwSupportedOptions - The options the object knows about(might not support)
  563. dwEnabledOptions - The options the object supports
  564. Return Value:
  565. HRESULT
  566. --*/
  567. {
  568. //
  569. // If we're being asked to set our safe for scripting or
  570. // safe for initialization options then oblige
  571. //
  572. if (0 == dwOptionSetMask && 0 == dwEnabledOptions)
  573. {
  574. //
  575. // the control certainly supports NO requests through the specified interface
  576. // so it's safe to return S_OK even if the interface isn't supported.
  577. //
  578. return S_OK;
  579. }
  580. SetupSecurityPolicy();
  581. if (riid == IID_IDispatch)
  582. {
  583. //
  584. // Client is asking if it is safe to call through IDispatch
  585. //
  586. if (INTERFACESAFE_FOR_UNTRUSTED_CALLER == dwOptionSetMask &&
  587. INTERFACESAFE_FOR_UNTRUSTED_CALLER == dwEnabledOptions)
  588. {
  589. return S_OK;
  590. }
  591. }
  592. else if (riid == IID_IPersistPropertyBag || riid == IID_IPersistStreamInit)
  593. {
  594. //
  595. // Client is asking if it's safe to call through IPersistXXX
  596. //
  597. if (INTERFACESAFE_FOR_UNTRUSTED_DATA == dwOptionSetMask &&
  598. INTERFACESAFE_FOR_UNTRUSTED_DATA == dwEnabledOptions)
  599. {
  600. return S_OK;
  601. }
  602. }
  603. return E_FAIL;
  604. }
  605. VOID
  606. CImpIObjectSafety::SetupSecurityPolicy()
  607. /*++
  608. Routine Description:
  609. The function check if we are safe for scripting.
  610. Arguments:
  611. None
  612. Return Value:
  613. Return TRUE if we are safe for scripting, othewise return FALSE
  614. --*/
  615. {
  616. HRESULT hr;
  617. IServiceProvider* pSrvProvider = NULL;
  618. IWebBrowser2* pWebBrowser = NULL;
  619. IInternetSecurityManager* pISM = NULL;
  620. BSTR bstrURL;
  621. DWORD dwContext = 0;
  622. g_dwScriptPolicy = URLPOLICY_ALLOW;
  623. //
  624. // Get the service provider
  625. //
  626. hr = m_pObj->m_pIOleClientSite->QueryInterface(IID_IServiceProvider, (void **)&pSrvProvider);
  627. if (SUCCEEDED(hr)) {
  628. hr = pSrvProvider->QueryService(SID_SWebBrowserApp,
  629. IID_IWebBrowser2,
  630. (void **)&pWebBrowser);
  631. }
  632. if (SUCCEEDED(hr)) {
  633. hr = pSrvProvider->QueryService(SID_SInternetSecurityManager,
  634. IID_IInternetSecurityManager,
  635. (void**)&pISM);
  636. }
  637. if (SUCCEEDED(hr)) {
  638. hr = pWebBrowser->get_LocationURL(&bstrURL);
  639. }
  640. //
  641. // Querying safe for scripting
  642. //
  643. if (SUCCEEDED(hr)) {
  644. hr = pISM->ProcessUrlAction(bstrURL,
  645. URLACTION_ACTIVEX_CONFIRM_NOOBJECTSAFETY,
  646. (BYTE*)&g_dwScriptPolicy,
  647. sizeof(g_dwScriptPolicy),
  648. (BYTE*)&dwContext,
  649. sizeof(dwContext),
  650. PUAF_NOUI,
  651. 0);
  652. }
  653. if (SUCCEEDED(hr)) {
  654. if (g_dwScriptPolicy == URLPOLICY_QUERY) {
  655. g_dwScriptPolicy = URLPOLICY_ALLOW;
  656. }
  657. if (g_dwScriptPolicy == URLPOLICY_DISALLOW) {
  658. if (!m_fMessageDisplayed) {
  659. m_fMessageDisplayed = TRUE;
  660. MessageBox(NULL,
  661. ResourceString(IDS_SCRIPT_NOT_ALLOWED),
  662. ResourceString(IDS_APP_NAME),
  663. MB_OK);
  664. }
  665. }
  666. }
  667. if (pWebBrowser) {
  668. pWebBrowser->Release();
  669. }
  670. if (pSrvProvider) {
  671. pSrvProvider->Release();
  672. }
  673. if (pISM) {
  674. pISM->Release();
  675. }
  676. }