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.

1245 lines
28 KiB

  1. /*===================================================================
  2. Microsoft Denali
  3. Microsoft Confidential.
  4. Copyright 1997 Microsoft Corporation. All Rights Reserved.
  5. Component: Viper Integration Objects
  6. File: viperint.cpp
  7. Owner: DmitryR
  8. This file contains the implementation of viper integration classes
  9. ===================================================================*/
  10. #include "denpre.h"
  11. #pragma hdrstop
  12. #include "Context.h"
  13. #include "package.h"
  14. #include "memchk.h"
  15. #include "svcintfs.h"
  16. extern HDESK ghDesktop;
  17. //
  18. // COM holds the last reference to a CViperAsyncRequest
  19. // we need to track these objects to ensure that we don't
  20. // exit before the activity threads have released them.
  21. //
  22. volatile LONG g_nViperRequests = 0;
  23. /*===================================================================
  24. C V i p e r A s y n c R e q u e s t
  25. ===================================================================*/
  26. /*===================================================================
  27. CViperAsyncRequest::CViperAsyncRequest
  28. CViperAsyncRequest constructor
  29. Parameters:
  30. Returns:
  31. ===================================================================*/
  32. CViperAsyncRequest::CViperAsyncRequest()
  33. : m_cRefs(1), m_pHitObj(NULL)
  34. {
  35. InterlockedIncrement( (LONG *)&g_nViperRequests );
  36. }
  37. /*===================================================================
  38. CViperAsyncRequest::~CViperAsyncRequest
  39. CViperAsyncRequest destructor
  40. Parameters:
  41. Returns:
  42. ===================================================================*/
  43. CViperAsyncRequest::~CViperAsyncRequest()
  44. {
  45. InterlockedDecrement( (LONG *)&g_nViperRequests );
  46. }
  47. /*===================================================================
  48. CViperAsyncRequest::Init
  49. Initialize CViperAsyncRequest with CHitObj object
  50. Parameters:
  51. CHitObj *pHitObj Denali HitObj
  52. Returns:
  53. HRESULT
  54. ===================================================================*/
  55. HRESULT CViperAsyncRequest::Init
  56. (
  57. CHitObj *pHitObj
  58. )
  59. {
  60. Assert(m_pHitObj == NULL);
  61. m_pHitObj = pHitObj;
  62. return S_OK;
  63. }
  64. #ifdef DBG
  65. /*===================================================================
  66. CViperAsyncRequest::AssertValid
  67. Test to make sure that this is currently correctly formed
  68. and assert if it is not.
  69. Returns:
  70. ===================================================================*/
  71. void CViperAsyncRequest::AssertValid() const
  72. {
  73. Assert(m_pHitObj);
  74. Assert(m_cRefs > 0);
  75. }
  76. #endif
  77. /*===================================================================
  78. CViperAsyncRequest::QueryInterface
  79. Standard IUnknown method
  80. Parameters:
  81. REFIID iid
  82. void **ppv
  83. Returns:
  84. HRESULT
  85. ===================================================================*/
  86. STDMETHODIMP CViperAsyncRequest::QueryInterface
  87. (
  88. REFIID iid,
  89. void **ppv
  90. )
  91. {
  92. if (iid == IID_IUnknown || iid == IID_IMTSCall)
  93. {
  94. *ppv = this;
  95. AddRef();
  96. return S_OK;
  97. }
  98. return E_NOINTERFACE;
  99. }
  100. /*===================================================================
  101. CViperAsyncRequest::AddRef
  102. Standard IUnknown method
  103. Parameters:
  104. Returns:
  105. Ref count
  106. ===================================================================*/
  107. STDMETHODIMP_(ULONG) CViperAsyncRequest::AddRef()
  108. {
  109. return ++m_cRefs;
  110. }
  111. /*===================================================================
  112. CViperAsyncRequest::Release
  113. Standard IUnknown method
  114. Parameters:
  115. Returns:
  116. Ref count
  117. ===================================================================*/
  118. STDMETHODIMP_(ULONG) CViperAsyncRequest::Release()
  119. {
  120. if (--m_cRefs != 0)
  121. return m_cRefs;
  122. delete this;
  123. return 0;
  124. }
  125. /*===================================================================
  126. CViperAsyncRequest::OnCall
  127. IMTSCall method implementation. This method is called by Viper
  128. from the right thread when it's time to process a request
  129. Parameters:
  130. Returns:
  131. HRESULT
  132. ===================================================================*/
  133. STDMETHODIMP CViperAsyncRequest::OnCall()
  134. {
  135. Assert(m_pHitObj);
  136. CIsapiReqInfo *pIReq = m_pHitObj->PIReq();
  137. BOOL fRequestReposted = FALSE;
  138. // add an extra addref here to prevent the deletion of the
  139. // hitobj deleting the CIsapiReqInfo for this request.
  140. if (pIReq)
  141. pIReq->AddRef();
  142. // Bracket ViperAsyncCallback
  143. if (SUCCEEDED(StartISAThreadBracket(pIReq)))
  144. {
  145. m_pHitObj->ViperAsyncCallback(&fRequestReposted);
  146. // Make sure there always is DONE_WITH_SESSION
  147. if (m_pHitObj->FIsBrowserRequest() && !fRequestReposted)
  148. {
  149. if (!m_pHitObj->FDoneWithSession())
  150. m_pHitObj->ReportServerError(IDE_UNEXPECTED);
  151. }
  152. if (!fRequestReposted)
  153. delete m_pHitObj; // don't delete if reposted
  154. EndISAThreadBracket(pIReq);
  155. }
  156. else
  157. {
  158. // DONE_WITH_SESSION -- ServerSupportFunction
  159. // does not need bracketing
  160. if (m_pHitObj->FIsBrowserRequest())
  161. m_pHitObj->ReportServerError(0);
  162. // We never called to process request, there should
  163. // be no state and it's probably save to delete it
  164. // outside of bracketing
  165. delete m_pHitObj;
  166. }
  167. m_pHitObj = NULL; // set to NULL even if not deleted
  168. Release(); // release this, Viper holds another ref
  169. if (pIReq)
  170. pIReq->Release();
  171. return S_OK;
  172. }
  173. /*===================================================================
  174. C V i p e r A c t i v i t y
  175. ===================================================================*/
  176. /*===================================================================
  177. CViperActivity::CViperActivity
  178. CViperActivity constructor
  179. Parameters:
  180. Returns:
  181. ===================================================================*/
  182. CViperActivity::CViperActivity()
  183. : m_pActivity(NULL), m_cBind(0)
  184. {
  185. }
  186. /*===================================================================
  187. CViperActivity::~CViperActivity
  188. CViperActivity destructor
  189. Parameters:
  190. Returns:
  191. ===================================================================*/
  192. CViperActivity::~CViperActivity()
  193. {
  194. UnInit();
  195. }
  196. /*===================================================================
  197. CViperActivity::Init
  198. Create actual Viper activity using MTSCreateActivity()
  199. Parameters:
  200. Returns:
  201. HRESULT
  202. ===================================================================*/
  203. HRESULT CViperActivity::Init(BOOL fCreateInMTA /* = FALSE */)
  204. {
  205. Assert(!FInited());
  206. HRESULT hr = S_OK;
  207. if (fCreateInMTA) {
  208. hr = CreateActivityInMTA
  209. (
  210. IID_IMTSActivity,
  211. (void **)&m_pActivity
  212. );
  213. }
  214. else {
  215. hr = MTSCreateActivity
  216. (
  217. IID_IMTSActivity,
  218. (void **)&m_pActivity
  219. );
  220. }
  221. if (FAILED(hr))
  222. return hr;
  223. m_cBind = 1;
  224. return S_OK;
  225. }
  226. /*===================================================================
  227. CViperActivity::InitClone
  228. Clone Viper activity (AddRef() it)
  229. Parameters:
  230. CViperActivity *pActivity activity to clone from
  231. Returns:
  232. HRESULT
  233. ===================================================================*/
  234. HRESULT CViperActivity::InitClone
  235. (
  236. CViperActivity *pActivity
  237. )
  238. {
  239. Assert(!FInited());
  240. Assert(pActivity);
  241. pActivity->AssertValid();
  242. m_pActivity = pActivity->m_pActivity;
  243. m_pActivity->AddRef();
  244. m_cBind = 1;
  245. return S_OK;
  246. }
  247. /*===================================================================
  248. CViperActivity::UnInit
  249. Release Viper activity
  250. Parameters:
  251. Returns:
  252. HRESULT
  253. ===================================================================*/
  254. HRESULT CViperActivity::UnInit()
  255. {
  256. if (m_pActivity)
  257. {
  258. while (m_cBind > 1) // 1 is for inited flag
  259. {
  260. m_pActivity->UnbindFromThread();
  261. m_cBind--;
  262. }
  263. m_pActivity->Release();
  264. m_pActivity = NULL;
  265. }
  266. m_cBind = 0;
  267. return S_OK;
  268. }
  269. /*===================================================================
  270. CViperActivity::BindToThread
  271. Bind Activity to current thread using IMTSActivity method
  272. Parameters:
  273. Returns:
  274. HRESULT
  275. ===================================================================*/
  276. HRESULT CViperActivity::BindToThread()
  277. {
  278. Assert(FInited());
  279. m_pActivity->BindToCurrentThread();
  280. m_cBind++;
  281. return S_OK;
  282. }
  283. /*===================================================================
  284. CViperActivity::UnBindFromThread
  285. UnBind Activity from using IMTSActivity method
  286. Parameters:
  287. Returns:
  288. HRESULT
  289. ===================================================================*/
  290. HRESULT CViperActivity::UnBindFromThread()
  291. {
  292. Assert(FInited());
  293. Assert(m_cBind > 1);
  294. m_pActivity->UnbindFromThread();
  295. m_cBind--;
  296. return S_OK;
  297. }
  298. /*===================================================================
  299. CViperActivity::PostAsyncRequest
  300. Call HitObj Async.
  301. Creates IMTSCCall object to do it.
  302. Parameters:
  303. CHitObj *pHitObj Denali's HitObj
  304. Returns:
  305. HRESULT
  306. ===================================================================*/
  307. HRESULT CViperActivity::PostAsyncRequest
  308. (
  309. CHitObj *pHitObj
  310. )
  311. {
  312. AssertValid();
  313. HRESULT hr = S_OK;
  314. CViperAsyncRequest *pViperCall = new CViperAsyncRequest;
  315. if (!pViperCall)
  316. hr = E_OUTOFMEMORY;
  317. if (SUCCEEDED(hr))
  318. hr = pViperCall->Init(pHitObj);
  319. RevertToSelf();
  320. if (SUCCEEDED(hr))
  321. hr = m_pActivity->AsyncCall(pViperCall);
  322. if (FAILED(hr) && pViperCall) // cleanup if failed
  323. pViperCall->Release();
  324. return hr;
  325. }
  326. /*===================================================================
  327. CViperActivity::PostGlobalAsyncRequest
  328. Static method.
  329. Post async request without an activity.
  330. Creates temporary activity
  331. Parameters:
  332. CHitObj *pHitObj Denali's HitObj
  333. Returns:
  334. HRESULT
  335. ===================================================================*/
  336. HRESULT CViperActivity::PostGlobalAsyncRequest
  337. (
  338. CHitObj *pHitObj
  339. )
  340. {
  341. HRESULT hr = S_OK;
  342. CViperActivity *pTmpActivity = new CViperActivity;
  343. if (!pTmpActivity)
  344. hr = E_OUTOFMEMORY;
  345. if (SUCCEEDED(hr))
  346. hr = pTmpActivity->Init();
  347. if (SUCCEEDED(hr))
  348. {
  349. // remember this activity as HitObj's activity
  350. // HitObj will get rid of it on its destructor
  351. pHitObj->SetActivity(pTmpActivity);
  352. hr = pTmpActivity->PostAsyncRequest(pHitObj);
  353. pTmpActivity = NULL; // don't delete, HitObj will
  354. }
  355. if (pTmpActivity)
  356. delete pTmpActivity;
  357. return hr;
  358. }
  359. #ifdef DBG
  360. /*===================================================================
  361. CViperAsyncRequest::AssertValid
  362. Test to make sure that this is currently correctly formed
  363. and assert if it is not.
  364. Returns:
  365. ===================================================================*/
  366. void CViperActivity::AssertValid() const
  367. {
  368. Assert(FInited());
  369. Assert(m_pActivity);
  370. }
  371. #endif
  372. #ifdef UNUSED
  373. /*===================================================================
  374. C V i p e r T h r e a d E v e n t s
  375. ===================================================================*/
  376. /*===================================================================
  377. CViperThreadEvents::CViperThreadEvents
  378. CViperThreadEvents constructor
  379. Parameters:
  380. Returns:
  381. ===================================================================*/
  382. CViperThreadEvents::CViperThreadEvents()
  383. : m_cRefs(1)
  384. {
  385. }
  386. #ifdef DBG
  387. /*===================================================================
  388. CViperThreadEvents::AssertValid
  389. Test to make sure that this is currently correctly formed
  390. and assert if it is not.
  391. Returns:
  392. ===================================================================*/
  393. void CViperThreadEvents::AssertValid() const
  394. {
  395. Assert(m_cRefs > 0);
  396. Assert(ghDesktop != NULL);
  397. }
  398. #endif
  399. /*===================================================================
  400. CViperThreadEvents::QueryInterface
  401. Standard IUnknown method
  402. Parameters:
  403. REFIID iid
  404. void **ppv
  405. Returns:
  406. HRESULT
  407. ===================================================================*/
  408. STDMETHODIMP CViperThreadEvents::QueryInterface
  409. (
  410. REFIID iid,
  411. void **ppv
  412. )
  413. {
  414. if (iid == IID_IUnknown || iid == IID_IThreadEvents)
  415. {
  416. *ppv = this;
  417. AddRef();
  418. return S_OK;
  419. }
  420. return E_NOINTERFACE;
  421. }
  422. /*===================================================================
  423. CViperThreadEvents::AddRef
  424. Standard IUnknown method
  425. Parameters:
  426. Returns:
  427. Ref count
  428. ===================================================================*/
  429. STDMETHODIMP_(ULONG) CViperThreadEvents::AddRef()
  430. {
  431. DWORD cRefs = InterlockedIncrement((LPLONG)&m_cRefs);
  432. return cRefs;
  433. }
  434. /*===================================================================
  435. CViperThreadEvents::Release
  436. Standard IUnknown method
  437. Parameters:
  438. Returns:
  439. Ref count
  440. ===================================================================*/
  441. STDMETHODIMP_(ULONG) CViperThreadEvents::Release()
  442. {
  443. DWORD cRefs = InterlockedDecrement((LPLONG)&m_cRefs);
  444. if (cRefs)
  445. return cRefs;
  446. delete this;
  447. return 0;
  448. }
  449. /*===================================================================
  450. CViperThreadEvents::OnStartup
  451. IThreadEvents method implementation. This method is called by Viper
  452. whenever they start up a thread.
  453. Parameters:
  454. None
  455. Returns:
  456. HRESULT
  457. ===================================================================*/
  458. STDMETHODIMP CViperThreadEvents::OnStartup()
  459. {
  460. HRESULT hr;
  461. AssertValid();
  462. // Set the desktop for this thread
  463. hr = SetDesktop();
  464. return hr;
  465. }
  466. /*===================================================================
  467. CViperThreadEvents::OnShutdown
  468. IThreadEvents method implementation. This method is called by Viper
  469. whenever they shut down a thread.
  470. Parameters:
  471. None
  472. Returns:
  473. HRESULT
  474. ===================================================================*/
  475. STDMETHODIMP CViperThreadEvents::OnShutdown()
  476. {
  477. AssertValid();
  478. return S_OK;
  479. }
  480. #endif //UNUSED
  481. /*===================================================================
  482. G l o b a l F u n c t i o n s
  483. ===================================================================*/
  484. /*===================================================================
  485. ViperSetContextProperty
  486. Static utility function.
  487. Set Viper context property by BSTR and IDispatch*.
  488. The real interface takes BSTR and VARIANT.
  489. Parameters
  490. IContextProperties *pContextProperties Context
  491. BSTR bstrPropertyName Name
  492. IDispatch *pdispPropertyValue Value
  493. Returns:
  494. HRESULT
  495. ===================================================================*/
  496. static HRESULT ViperSetContextProperty
  497. (
  498. IContextProperties *pContextProperties,
  499. BSTR bstrPropertyName,
  500. IDispatch *pdispPropertyValue
  501. )
  502. {
  503. // Make VARIANT from IDispatch*
  504. pdispPropertyValue->AddRef();
  505. VARIANT Variant;
  506. VariantInit(&Variant);
  507. V_VT(&Variant) = VT_DISPATCH;
  508. V_DISPATCH(&Variant) = pdispPropertyValue;
  509. // Call Viper to set the property
  510. HRESULT hr = pContextProperties->SetProperty
  511. (
  512. bstrPropertyName,
  513. Variant
  514. );
  515. // Cleanup
  516. VariantClear(&Variant);
  517. return hr;
  518. }
  519. /*===================================================================
  520. ViperAttachIntrinsicsToContext
  521. Attach ASP intrinsic objects as Viper context properties
  522. Parameters - Intrinsics as interface pointers
  523. IApplicationObject *pAppln Application (required)
  524. ISessionObject *pSession Session (optional)
  525. IRequest *pRequest Request (optional)
  526. IResponse *pResponse Response (optional)
  527. IServer *pServer Server (optional)
  528. Returns:
  529. HRESULT
  530. ===================================================================*/
  531. HRESULT ViperAttachIntrinsicsToContext
  532. (
  533. IApplicationObject *pAppln,
  534. ISessionObject *pSession,
  535. IRequest *pRequest,
  536. IResponse *pResponse,
  537. IServer *pServer
  538. )
  539. {
  540. Assert(pAppln);
  541. HRESULT hr = S_OK;
  542. // Get Viper Context
  543. IObjectContext *pViperContext = NULL;
  544. hr = GetObjectContext(&pViperContext);
  545. // Get IContextPoperties interface
  546. IContextProperties *pContextProperties = NULL;
  547. if (SUCCEEDED(hr))
  548. hr = pViperContext->QueryInterface
  549. (
  550. IID_IContextProperties,
  551. (void **)&pContextProperties
  552. );
  553. // Set properties
  554. if (SUCCEEDED(hr))
  555. hr = ViperSetContextProperty
  556. (
  557. pContextProperties,
  558. BSTR_OBJ_APPLICATION,
  559. pAppln
  560. );
  561. if (SUCCEEDED(hr) && pSession)
  562. hr = ViperSetContextProperty
  563. (
  564. pContextProperties,
  565. BSTR_OBJ_SESSION,
  566. pSession
  567. );
  568. if (SUCCEEDED(hr) && pRequest)
  569. hr = ViperSetContextProperty
  570. (
  571. pContextProperties,
  572. BSTR_OBJ_REQUEST,
  573. pRequest
  574. );
  575. if (SUCCEEDED(hr) && pResponse)
  576. hr = ViperSetContextProperty
  577. (
  578. pContextProperties,
  579. BSTR_OBJ_RESPONSE,
  580. pResponse
  581. );
  582. if (SUCCEEDED(hr) && pServer)
  583. hr = ViperSetContextProperty
  584. (
  585. pContextProperties,
  586. BSTR_OBJ_SERVER,
  587. pServer
  588. );
  589. // Cleanup
  590. if (pContextProperties)
  591. pContextProperties->Release();
  592. if (pViperContext)
  593. pViperContext->Release();
  594. return hr;
  595. }
  596. /*===================================================================
  597. ViperGetObjectFromContext
  598. Get Viper context property by LPWSTR and
  599. return it as IDispatch*.
  600. The real interface takes BSTR and VARIANT.
  601. Parameters
  602. BSTR bstrName Property Name
  603. IDispatch **ppdisp [out] Object (Property Value)
  604. Returns:
  605. HRESULT
  606. ===================================================================*/
  607. HRESULT ViperGetObjectFromContext
  608. (
  609. BSTR bstrName,
  610. IDispatch **ppdisp
  611. )
  612. {
  613. Assert(ppdisp);
  614. HRESULT hr = S_OK;
  615. // Get Viper Context
  616. IObjectContext *pViperContext = NULL;
  617. hr = GetObjectContext(&pViperContext);
  618. // Get IContextPoperties interface
  619. IContextProperties *pContextProperties = NULL;
  620. if (SUCCEEDED(hr))
  621. hr = pViperContext->QueryInterface
  622. (
  623. IID_IContextProperties,
  624. (void **)&pContextProperties
  625. );
  626. // Get property Value as variant
  627. VARIANT Variant;
  628. VariantInit(&Variant);
  629. if (SUCCEEDED(hr))
  630. hr = pContextProperties->GetProperty(bstrName, &Variant);
  631. // Convert Variant to IDispatch*
  632. if (SUCCEEDED(hr))
  633. {
  634. IDispatch *pDisp = NULL;
  635. if (V_VT(&Variant) == VT_DISPATCH)
  636. pDisp = V_DISPATCH(&Variant);
  637. if (pDisp)
  638. {
  639. pDisp->AddRef();
  640. *ppdisp = pDisp;
  641. }
  642. else
  643. hr = E_FAIL;
  644. }
  645. // Cleanup
  646. VariantClear(&Variant);
  647. if (pContextProperties)
  648. pContextProperties->Release();
  649. if (pViperContext)
  650. pViperContext->Release();
  651. if (FAILED(hr))
  652. *ppdisp = NULL;
  653. return hr;
  654. }
  655. /*===================================================================
  656. ViperGetHitObjFromContext
  657. Get Server from Viper context property and get
  658. it's current HitObj
  659. Parameters
  660. CHitObj **ppHitObj [out]
  661. Returns:
  662. HRESULT
  663. ===================================================================*/
  664. HRESULT ViperGetHitObjFromContext
  665. (
  666. CHitObj **ppHitObj
  667. )
  668. {
  669. *ppHitObj = NULL;
  670. IDispatch *pdispServer = NULL;
  671. HRESULT hr = ViperGetObjectFromContext(BSTR_OBJ_SERVER, &pdispServer);
  672. if (FAILED(hr))
  673. return hr;
  674. if (pdispServer)
  675. {
  676. CServer *pServer = static_cast<CServer *>(pdispServer);
  677. *ppHitObj = pServer->PHitObj();
  678. pdispServer->Release();
  679. }
  680. return *ppHitObj ? S_OK : S_FALSE;
  681. }
  682. /*===================================================================
  683. ViperCreateInstance
  684. Viper's implementation of CoCreateInstance
  685. Parameters
  686. REFCLSID rclsid class id
  687. REFIID riid interface
  688. void **ppv [out] pointer to interface
  689. Returns:
  690. HRESULT
  691. ===================================================================*/
  692. HRESULT ViperCreateInstance
  693. (
  694. REFCLSID rclsid,
  695. REFIID riid,
  696. void **ppv
  697. )
  698. {
  699. /*
  700. DWORD dwClsContext = (Glob(fAllowOutOfProcCmpnts)) ?
  701. CLSCTX_INPROC_SERVER | CLSCTX_SERVER :
  702. CLSCTX_INPROC_SERVER;
  703. */
  704. // The reasons for supporting ASPAllowOutOfProcComponents seem to have
  705. // vanished. Because this only partially worked in II4 and we changed
  706. // the default in IIS5 this was causing problems with upgrades. So
  707. // we're going to ignore the fAllowOutOfProcCmpnts setting.
  708. DWORD dwClsContext = CLSCTX_INPROC_SERVER | CLSCTX_SERVER;
  709. return CoCreateInstance(rclsid, NULL, dwClsContext, riid, ppv);
  710. }
  711. /*
  712. {
  713. HRESULT hr = S_OK;
  714. DWORD dwClsContext;
  715. IObjectContext *pViperContext = NULL;
  716. hr = GetObjectContext(&pViperContext);
  717. if (SUCCEEDED(hr))
  718. {
  719. hr = pViperContext->CreateInstance(rclsid, riid, ppv);
  720. pViperContext->Release();
  721. // If we got back CLASSNOTREG, it might be an OOP Non-MTS component.
  722. // If so, and we are allowing OOP components, then try again with CoCreateInstance
  723. if (hr == REGDB_E_CLASSNOTREG && Glob(fAllowOutOfProcCmpnts))
  724. {
  725. dwClsContext = (FIsWinNT()) ? CLSCTX_SERVER : CLSCTX_LOCAL_SERVER;
  726. hr = CoCreateInstance(rclsid, NULL, dwClsContext,
  727. riid, ppv);
  728. }
  729. }
  730. else
  731. {
  732. // no Viper context -> use regular CoCreateInstance
  733. // (set flag to allow any server type)
  734. dwClsContext = CLSCTX_INPROC_SERVER;
  735. if (Glob(fAllowOutOfProcCmpnts))
  736. {
  737. // If out of proc is allowed, or in the appropriate flag
  738. dwClsContext |= (FIsWinNT()) ? CLSCTX_SERVER : CLSCTX_LOCAL_SERVER;
  739. }
  740. hr = CoCreateInstance(rclsid, NULL, dwClsContext, riid, ppv);
  741. }
  742. return hr;
  743. }
  744. */
  745. #ifdef UNUSED
  746. /*===================================================================
  747. SetViperThreadEvents
  748. Give Viper a pair of callbacks to call when the startup and shutdown
  749. their threads
  750. Parameters
  751. None
  752. Returns:
  753. HRESULT
  754. To use the latter, take your IMTSPackage and QI for IID_IThreadEventSource. (If not there,
  755. you don't yet have the feature.) Then do:
  756. IThreadEvents* psink = new CAndrewsThreadEventSink;
  757. psource->RegisterThreadEventSink(psink);
  758. ===================================================================*/
  759. HRESULT SetViperThreadEvents()
  760. {
  761. HRESULT hr = S_OK;
  762. IMTSPackage *pPackage = NULL;
  763. IThreadEventSource *pSource = NULL;
  764. IThreadEvents *pSink = NULL;
  765. // Get hold of the package
  766. hr = CoCreateInstance(CLSID_MTSPackage,
  767. NULL,
  768. CLSCTX_INPROC_SERVER,
  769. IID_IMTSPackage,
  770. (void **)&pPackage);
  771. if (FAILED(hr) || !pPackage)
  772. goto LErr;
  773. hr = pPackage->QueryInterface(IID_IThreadEventSource,
  774. (void **)&pSource);
  775. if (hr == E_NOINTERFACE)
  776. {
  777. // This error means that we are running against a version of MTX that doesnt
  778. // support this. Oh well.
  779. hr = S_OK;
  780. goto LErr;
  781. }
  782. if (FAILED(hr))
  783. goto LErr;
  784. pSink = new CViperThreadEvents;
  785. if (pSink == NULL)
  786. {
  787. hr = E_OUTOFMEMORY;
  788. goto LErr;
  789. }
  790. pSource->RegisterThreadEventSink(pSink);
  791. LErr:
  792. if (pSource)
  793. pSource->Release();
  794. if (pPackage)
  795. pPackage->Release();
  796. return hr;
  797. }
  798. #endif //UNUSED
  799. /*===================================================================
  800. ViperConfigure
  801. Viper settings: # of threads, queue len,
  802. in-proc failfast,
  803. allow oop components
  804. Parameters
  805. cThreads -- number of threads
  806. fAllowOopComponents -- TRUE or FALSE
  807. Returns:
  808. HRESULT
  809. ===================================================================*/
  810. HRESULT ViperConfigure
  811. (
  812. DWORD cThreads,
  813. BOOL fAllowOopComponents
  814. )
  815. {
  816. HRESULT hr = S_OK;
  817. IMTSPackage *pPackage = NULL;
  818. //
  819. // Get hold of the package
  820. //
  821. hr = CoCreateInstance(CLSID_MTSPackage,
  822. NULL,
  823. CLSCTX_INPROC_SERVER,
  824. IID_IMTSPackage,
  825. (void **)&pPackage);
  826. if (SUCCEEDED(hr) && !pPackage)
  827. hr = E_FAIL;
  828. //
  829. // Set knobs
  830. //
  831. if (SUCCEEDED(hr))
  832. {
  833. #define MTS_STYLE_THREAD_POOL
  834. #ifdef MTS_STYLE_THREAD_POOL
  835. IComStaThreadPoolKnobs *pKnobs = NULL;
  836. hr = pPackage->QueryInterface(IID_IComStaThreadPoolKnobs, (void **)&pKnobs);
  837. #else
  838. IThreadPoolKnobs *pKnobs = NULL;
  839. hr = pPackage->QueryInterface(IID_IThreadPoolKnobs, (void **)&pKnobs);
  840. #endif
  841. if (SUCCEEDED(hr) && pKnobs)
  842. {
  843. // number of threads
  844. SYSTEM_INFO si;
  845. GetSystemInfo(&si);
  846. cThreads *= si.dwNumberOfProcessors;
  847. #ifdef MTS_STYLE_THREAD_POOL
  848. pKnobs->SetMaxThreadCount(cThreads);
  849. pKnobs->SetMinThreadCount(si.dwNumberOfProcessors + 7);
  850. // queue length
  851. pKnobs->SetQueueDepth(30000);
  852. pKnobs->SetActivityPerThread(1);
  853. #else
  854. pKnobs->SetMaxThreads(cThreads);
  855. pKnobs->SetMinThreads(si.dwNumberOfProcessors + 7);
  856. // queue length
  857. pKnobs->SetMaxQueuedRequests(30000);
  858. #endif
  859. pKnobs->Release();
  860. }
  861. }
  862. //
  863. // Bug 111008: Tell Viper that we do impersonations
  864. //
  865. if (SUCCEEDED(hr))
  866. {
  867. IImpersonationControl *pImpControl = NULL;
  868. hr = pPackage->QueryInterface(IID_IImpersonationControl, (void **)&pImpControl);
  869. if (SUCCEEDED(hr) && pImpControl)
  870. {
  871. hr = pImpControl->ClientsImpersonate(TRUE);
  872. pImpControl->Release();
  873. }
  874. }
  875. //
  876. // Disable FAILFAST for in-proc case
  877. //
  878. if (SUCCEEDED(hr) && !g_fOOP)
  879. {
  880. IFailfastControl *pFFControl = NULL;
  881. hr = pPackage->QueryInterface(IID_IFailfastControl, (void **)&pFFControl);
  882. if (SUCCEEDED(hr) && pFFControl)
  883. {
  884. pFFControl->SetApplFailfast(FALSE);
  885. pFFControl->Release();
  886. }
  887. }
  888. /*
  889. //
  890. // Set Allow OOP Components
  891. //
  892. if (SUCCEEDED(hr))
  893. {
  894. INonMTSActivation *pNonMTSActivation = NULL;
  895. hr = pPackage->QueryInterface(IID_INonMTSActivation, (void **)&pNonMTSActivation);
  896. if (SUCCEEDED(hr) && pNonMTSActivation)
  897. {
  898. pNonMTSActivation->OutOfProcActivationAllowed(fAllowOopComponents);
  899. pNonMTSActivation->Release();
  900. }
  901. }
  902. */
  903. //
  904. // Clean-up
  905. //
  906. if (pPackage)
  907. pPackage->Release();
  908. return hr;
  909. }
  910. /*===================================================================
  911. C O M H e l p e r A P I
  912. ===================================================================*/
  913. /*===================================================================
  914. ViperCoObjectIsaProxy
  915. Checks if the given IUnknown* points to a proxy
  916. Parameters
  917. IUnknown* pUnk pointer to check
  918. Returns:
  919. BOOL (TRUE if Proxy)
  920. ===================================================================*/
  921. BOOL ViperCoObjectIsaProxy
  922. (
  923. IUnknown* pUnk
  924. )
  925. {
  926. HRESULT hr;
  927. IUnknown *pUnk2;
  928. hr = pUnk->QueryInterface(IID_IProxyManager, (void**)&pUnk2);
  929. if (FAILED(hr))
  930. return FALSE;
  931. pUnk2->Release();
  932. return TRUE;
  933. }
  934. /*===================================================================
  935. ViperCoObjectAggregatesFTM
  936. Checks if the given object agregates free threaded marshaller
  937. (is agile)
  938. Parameters
  939. IUnknown* pUnk pointer to check
  940. Returns:
  941. BOOL (TRUE if Agile)
  942. ===================================================================*/
  943. BOOL ViperCoObjectAggregatesFTM
  944. (
  945. IUnknown *pUnk
  946. )
  947. {
  948. HRESULT hr;
  949. IMarshal *pMarshal;
  950. GUID guidClsid;
  951. hr = pUnk->QueryInterface(IID_IMarshal, (void**)&pMarshal);
  952. if (FAILED(hr))
  953. return FALSE;
  954. hr = pMarshal->GetUnmarshalClass(IID_IUnknown, pUnk, MSHCTX_INPROC,
  955. NULL, MSHLFLAGS_NORMAL, &guidClsid);
  956. pMarshal->Release();
  957. if (FAILED(hr))
  958. return FALSE;
  959. return (guidClsid == CLSID_InProcFreeMarshaler);
  960. }