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.

893 lines
18 KiB

  1. /*=====================================================================*
  2. Copyright (c) 1995-1997 Microsoft Corporation
  3. Module Name :
  4. wamxbase.cxx
  5. Abstract:
  6. Declaration of WAM_EXEC_BASE Object
  7. Author:
  8. David L. Kaplan ( DaveK ) 26-June-1997
  9. Environment:
  10. User Mode - Win32
  11. Project:
  12. WAM and ASP DLLs
  13. Revision History:
  14. ======================================================================*/
  15. # include "isapip.hxx"
  16. # include "wamxbase.hxx"
  17. # include "gip.h"
  18. // MIDL-generated
  19. # include "iwr.h"
  20. /*---------------------------------------------------------------------*
  21. WAM_EXEC_BASE::WAM_EXEC_BASE
  22. Constructor
  23. */
  24. WAM_EXEC_BASE::WAM_EXEC_BASE(
  25. )
  26. :
  27. m_dwThreadIdIIS ( 0 ) // threadid 0 can't happen in IIS
  28. , m_dwThreadIdISA ( 0 ) // threadid 0 can't happen in IIS
  29. , m_pIWamReqIIS ( NULL )
  30. , m_pIWamReqInproc ( NULL )
  31. , m_pIWamReqSmartISA( NULL )
  32. , m_gipIWamRequest ( 0 )
  33. , _dwIsaKeepConn ( KEEPCONN_OLD_ISAPI ) // per fix to #117107
  34. {
  35. IF_DEBUG( WAM_IWAMREQ_REFS ) {
  36. //
  37. // NOTE when WAM_IWAMREQ_REFS flag is set, we use
  38. // m_dwSignature as a ref count for gip get/release
  39. // (rather than add another debug-only member)
  40. //
  41. m_dwSignature = 0;
  42. }
  43. }
  44. /*---------------------------------------------------------------------*
  45. WAM_EXEC_BASE::InitWamExecBase
  46. Inits this structure by setting interface ptr members
  47. based on whether we are in-proc or oop.
  48. */
  49. HRESULT
  50. WAM_EXEC_BASE::InitWamExecBase(
  51. IWamRequest * pIWamRequest
  52. )
  53. {
  54. HRESULT hr = NOERROR;
  55. //
  56. // cache pointer passed to us by IIS
  57. // and thread id on which IIS called us
  58. //
  59. // NOTE we don't addref the ptr because we may not
  60. // actually use it. If we decide to use the ptr
  61. // (e.g. in-proc, or oop-smart-ISA on IIS thread),
  62. // we will addref then.
  63. //
  64. m_pIWamReqIIS = pIWamRequest;
  65. m_dwThreadIdIIS = GetCurrentThreadId();
  66. if ( m_fInProcess ) {
  67. //
  68. // In-Proc
  69. //
  70. // Cache and addref wamreq, since we will use its ptr
  71. //
  72. m_pIWamReqInproc = pIWamRequest;
  73. m_pIWamReqInproc->AddRef();
  74. // Remember wamreq in m_pIWamReqSmartISA as well to make
  75. // wamreq available in all cases for smart (caching)
  76. // ISAPIs like ASP simply by referring to m_pIWamReqSmartISA
  77. m_pIWamReqSmartISA = m_pIWamReqInproc;
  78. } else {
  79. //
  80. // Out-Proc
  81. //
  82. // Register wamreq with gip-master
  83. //
  84. // NOTE gip.Register addref's implicitly
  85. //
  86. hr = RegisterIWamRequest( pIWamRequest );
  87. }
  88. return hr;
  89. } // WAM_EXEC_BASE::InitWamExecBase
  90. /*---------------------------------------------------------------------*
  91. WAM_EXEC_BASE::CleanupWamExecBase
  92. Cleans up this structure by setting interface ptr members
  93. based on whether we are in-proc or oop.
  94. */
  95. VOID
  96. WAM_EXEC_BASE::CleanupWamExecBase(
  97. )
  98. {
  99. if ( m_fInProcess ) {
  100. //
  101. // In-proc
  102. //
  103. // Release the member wamreq ptr we cached at init
  104. //
  105. DBG_ASSERT( AssertInpValid() );
  106. m_pIWamReqInproc->Release();
  107. m_pIWamReqInproc = NULL;
  108. m_pIWamReqSmartISA = NULL;
  109. } else {
  110. //
  111. // Out-proc
  112. //
  113. // Revoke the gip cookie
  114. //
  115. DBG_ASSERT( AssertOopValid() );
  116. RevokeIWamRequest();
  117. }
  118. return;
  119. } // WAM_EXEC_BASE::CleanupWamExecBase
  120. /*---------------------------------------------------------------------*
  121. WAM_EXEC_BASE::RegisterIWamRequest
  122. For oop use only.
  123. Registers our W3-thread IWamRequest ptr with gip-master.
  124. Arguments:
  125. None
  126. Returns:
  127. HRESULT
  128. */
  129. HRESULT
  130. WAM_EXEC_BASE::RegisterIWamRequest(
  131. IWamRequest * pIWamRequest
  132. )
  133. {
  134. HRESULT hr = NOERROR;
  135. DBG_ASSERT ( !m_fInProcess );
  136. DBG_ASSERT( pIWamRequest );
  137. //
  138. // Register iwamreq ptr with gip-master
  139. //
  140. if ( FAILED( hr = g_GIPAPI.Register(
  141. pIWamRequest
  142. , IID_IWamRequest
  143. , &m_gipIWamRequest
  144. ))) {
  145. DBGPRINTF((
  146. DBG_CONTEXT
  147. , "g_GIPAPI.Register failed "
  148. "hr(%08x) "
  149. "m_gipIWamRequest(%08x) "
  150. "\n"
  151. , hr
  152. , m_gipIWamRequest
  153. ));
  154. } else {
  155. DBG_ASSERT( AssertOopValid() );
  156. }
  157. return hr;
  158. }
  159. /*---------------------------------------------------------------------*
  160. WAM_EXEC_BASE::RevokeIWamRequest
  161. If oop, revokes our gip-cookie.
  162. Arguments:
  163. None
  164. Returns:
  165. Nothing
  166. */
  167. VOID
  168. WAM_EXEC_BASE::RevokeIWamRequest(
  169. )
  170. {
  171. DBG_ASSERT( AssertOopValid() );
  172. //
  173. // Revoke the gip-cookie we got from gip-master at init
  174. //
  175. g_GIPAPI.Revoke( m_gipIWamRequest );
  176. return;
  177. }
  178. /*---------------------------------------------------------------------*
  179. WAM_EXEC_BASE::GetInterfaceForThread
  180. Caches a current-thread-valid IWamRequest ptr in m_pIWamReqSmartISA
  181. Arguments:
  182. None
  183. Returns:
  184. HRESULT
  185. */
  186. HRESULT
  187. WAM_EXEC_BASE::GetInterfaceForThread(
  188. )
  189. {
  190. HRESULT hr = NOERROR;
  191. DBG_ASSERT( m_pIWamReqSmartISA == NULL );
  192. DBG_ASSERT( m_dwThreadIdISA == 0 );
  193. DBG_ASSERT( AssertOopValid() );
  194. m_dwThreadIdISA = GetCurrentThreadId();
  195. IF_DEBUG( WAM_THREADID ) {
  196. DBGPRINTF((
  197. DBG_CONTEXT
  198. , "WAM_EXEC_BASE(%08x)::GetInterfaceForThread "
  199. "m_dwThreadIdIIS(%d) "
  200. "m_dwThreadIdISA(%d) "
  201. "\n"
  202. , this
  203. , m_dwThreadIdIIS
  204. , m_dwThreadIdISA
  205. ));
  206. }
  207. if ( m_dwThreadIdISA == m_dwThreadIdIIS ) {
  208. //
  209. // ISA called us on mainline (IIS) thread
  210. // so we can simply use cached ptr passed in by IIS.
  211. //
  212. m_pIWamReqSmartISA = m_pIWamReqIIS;
  213. //
  214. // addref the ptr since we are using it.
  215. //
  216. m_pIWamReqSmartISA->AddRef();
  217. } else {
  218. //
  219. // ISA called us on its own thread
  220. // so we must get a ptr from gip.
  221. //
  222. hr = GetInterfaceFromGip( &m_pIWamReqSmartISA );
  223. IF_DEBUG( WAM_THREADID ) {
  224. DBGPRINTF((
  225. DBG_CONTEXT
  226. , "GetInterfaceFromGip returned %d"
  227. "\n"
  228. , hr
  229. ));
  230. DBGPRINTF((
  231. DBG_CONTEXT
  232. , "m_dwThreadIdISA(%d)"
  233. "\n"
  234. , m_dwThreadIdISA
  235. ));
  236. }
  237. }
  238. return hr;
  239. } // WAM_EXEC_BASE::GetInterfaceForThread
  240. /*---------------------------------------------------------------------*
  241. WAM_EXEC_BASE::ReleaseInterfaceForThread
  242. Releases the IWamRequest ptr cached in m_pIWamReqSmartISA
  243. Arguments:
  244. None
  245. Returns:
  246. HRESULT
  247. */
  248. HRESULT
  249. WAM_EXEC_BASE::ReleaseInterfaceForThread(
  250. )
  251. {
  252. DBG_ASSERT( AssertOopValid() );
  253. if ( m_pIWamReqSmartISA == NULL ) {
  254. //
  255. // In some races, ISA-thread ptr was already released.
  256. // This is harmless, so we no-op.
  257. //
  258. DBGPRINTF((
  259. DBG_CONTEXT
  260. , "WAM_EXEC_BASE(%08x)::ReleaseInterfaceForThread\n"
  261. "\t Cached ISA-thread ptr already released\n"
  262. "\t m_dwThreadIdISA(%d)\n"
  263. "\t Current thread id(%d)\n"
  264. "\t m_pIWamReqSmartISA(%d)\n"
  265. , this
  266. , m_dwThreadIdISA
  267. , GetCurrentThreadId()
  268. , m_pIWamReqSmartISA
  269. ));
  270. return NOERROR;
  271. }
  272. DBG_ASSERT( AssertSmartISAValid() );
  273. if ( m_dwThreadIdISA != GetCurrentThreadId() ) {
  274. //
  275. // If thread id's don't match, we can't release
  276. //
  277. DBGPRINTF((
  278. DBG_CONTEXT
  279. , "WAM_EXEC_BASE(%08x)::ReleaseInterfaceForThread\n"
  280. "\t Wrong thread error\n"
  281. "\t m_dwThreadIdISA(%d)\n"
  282. "\t Current thread id(%d)\n"
  283. "\t m_pIWamReqSmartISA(%d)\n"
  284. , this
  285. , m_dwThreadIdISA
  286. , GetCurrentThreadId()
  287. , m_pIWamReqSmartISA
  288. ));
  289. //
  290. // Aha! If COM can return this, so can we ...
  291. //
  292. return RPC_E_WRONG_THREAD;
  293. }
  294. m_pIWamReqSmartISA->Release();
  295. m_pIWamReqSmartISA = NULL;
  296. m_dwThreadIdISA = 0;
  297. return NOERROR;
  298. }
  299. /*---------------------------------------------------------------------*
  300. WAM_EXEC_BASE::GetIWamRequest
  301. Returns a thread-valid IWamRequest ptr.
  302. Arguments:
  303. ppIWamRequest - returned ptr
  304. Returns:
  305. HRESULT
  306. */
  307. HRESULT
  308. WAM_EXEC_BASE::GetIWamRequest(
  309. IWamRequest ** ppIWamRequest
  310. )
  311. {
  312. HRESULT hrRet = NOERROR;
  313. IF_DEBUG( WAM_IWAMREQ_REFS ) {
  314. //
  315. // NOTE when WAM_IWAMREQ_REFS flag is set, we use
  316. // m_dwSignature as a ref count for gip get/release
  317. // (rather than add another debug-only member)
  318. //
  319. m_dwSignature++;
  320. DBGPRINTF((
  321. DBG_CONTEXT
  322. , "WAM_EXEC_BASE(%08x)::GetIWamRequest"
  323. " %d -> %d"
  324. "\n"
  325. , this
  326. , m_dwSignature - 1
  327. , m_dwSignature
  328. ));
  329. }
  330. if ( m_fInProcess ) {
  331. //
  332. // In-Proc: simply return our cached W3-thread ptr
  333. //
  334. DBG_ASSERT( AssertInpValid() );
  335. *ppIWamRequest = m_pIWamReqInproc;
  336. IF_DEBUG( WAM_REFCOUNTS ) {
  337. DBGPRINTF((
  338. DBG_CONTEXT
  339. , "WAM_EXEC_BASE(%08x)::GetIWamRequest"
  340. "\tIn-proc m_pIWamReqInproc(%08x)"
  341. "\n"
  342. , this
  343. , m_pIWamReqInproc
  344. ));
  345. }
  346. } else {
  347. //
  348. // Out-of-Proc:
  349. // If we are dealing with a 'smart ISA', use ISA-thread ptr
  350. //
  351. // Else if we are on 'IIS thread', use 'IIS ptr'
  352. //
  353. // Else, get a ptr from gip-master
  354. //
  355. //
  356. DBG_ASSERT( AssertOopValid() );
  357. if ( m_pIWamReqSmartISA ) {
  358. //
  359. // FAST
  360. //
  361. // 'Smart ISA' ==> use ISA-thread ptr
  362. //
  363. DBG_ASSERT( AssertSmartISAValid() );
  364. *ppIWamRequest = m_pIWamReqSmartISA;
  365. IF_DEBUG( WAM_REFCOUNTS ) {
  366. DBGPRINTF((
  367. DBG_CONTEXT
  368. , "WAM_EXEC_BASE(%08x)::GetIWamRequest"
  369. "\tOut-of-proc optimized - smart ISA: "
  370. "m_pIWamReqSmartISA(%08x)"
  371. "\n"
  372. , this
  373. , m_pIWamReqSmartISA
  374. ));
  375. }
  376. } else if ( GetCurrentThreadId() == m_dwThreadIdIIS ) {
  377. //
  378. // FAST
  379. //
  380. // We are on 'IIS thread' ==> use 'IIS ptr'
  381. // NOTE we addref it as a precaution
  382. //
  383. *ppIWamRequest = m_pIWamReqIIS;
  384. m_pIWamReqIIS->AddRef();
  385. IF_DEBUG( WAM_REFCOUNTS ) {
  386. DBGPRINTF((
  387. DBG_CONTEXT
  388. , "WAM_EXEC_BASE(%08x)::GetIWamRequest"
  389. "\tOut-of-proc optimized - IIS thread: "
  390. "m_pIWamReqIIS(%08x)"
  391. "\n"
  392. , this
  393. , m_pIWamReqIIS
  394. ));
  395. }
  396. } else {
  397. //
  398. // SLOW :-(
  399. //
  400. // ISA is not smart and we are not on IIS thread
  401. // ==> must get a ptr from gip
  402. //
  403. hrRet = GetInterfaceFromGip( ppIWamRequest );
  404. IF_DEBUG( WAM_REFCOUNTS ) {
  405. DBGPRINTF((
  406. DBG_CONTEXT
  407. , "WAM_EXEC_BASE(%08x)::GetIWamRequest"
  408. "\tOut-of-proc NOT optimized: *ppIWamRequest(%08x)"
  409. "\n"
  410. , this
  411. , *ppIWamRequest
  412. ));
  413. }
  414. }
  415. } // ( m_fInProcess )
  416. return hrRet;
  417. } // WAM_EXEC_BASE::GetIWamRequest
  418. /*---------------------------------------------------------------------*
  419. WAM_EXEC_BASE::ReleaseIWamRequest
  420. Releases an IWamRequest ptr, covering whether in-proc or out-proc.
  421. Arguments:
  422. pIWamRequest - ptr to release
  423. Returns:
  424. Nothing
  425. */
  426. VOID
  427. WAM_EXEC_BASE::ReleaseIWamRequest(
  428. IWamRequest * pIWamRequest
  429. )
  430. {
  431. IF_DEBUG( WAM_IWAMREQ_REFS ) {
  432. //
  433. // NOTE when WAM_IWAMREQ_REFS flag is set, we use
  434. // m_dwSignature as a ref count for gip get/release
  435. // (rather than add another debug-only member)
  436. //
  437. m_dwSignature--;
  438. DBGPRINTF((
  439. DBG_CONTEXT
  440. , "WAM_EXEC_BASE(%08x)::ReleaseIWamRequest"
  441. " %d -> %d"
  442. "\n"
  443. , this
  444. , m_dwSignature + 1
  445. , m_dwSignature
  446. ));
  447. }
  448. if ( m_fInProcess ) {
  449. DBG_ASSERT( AssertInpValid() );
  450. //
  451. // In-Proc: no-op
  452. //
  453. return;
  454. }
  455. if ( m_pIWamReqSmartISA && (pIWamRequest == m_pIWamReqSmartISA) ) {
  456. DBG_ASSERT( AssertSmartISAValid() );
  457. //
  458. // 'Smart ISA': no-op
  459. //
  460. return;
  461. }
  462. //
  463. // Out-Proc: release ptr
  464. //
  465. // NOTE the ptr is either our cached 'IIS ptr' (if we are on
  466. // mainline thread) or the one we got from gip-master
  467. // (if we are on another thread).
  468. //
  469. // Either way, we simply release it.
  470. //
  471. DBG_ASSERT( AssertOopValid() );
  472. IF_DEBUG( WAM_REFCOUNTS ) {
  473. DBGPRINTF((
  474. DBG_CONTEXT
  475. , "WAM_EXEC_BASE(%08x)::ReleaseIWamRequest ptr %08x\n"
  476. , this
  477. , pIWamRequest
  478. ));
  479. }
  480. pIWamRequest->Release();
  481. return;
  482. } // WAM_EXEC_BASE::ReleaseIWamRequest
  483. /*---------------------------------------------------------------------*
  484. WAM_EXEC_BASE::GetInterfaceFromGip
  485. */
  486. HRESULT
  487. WAM_EXEC_BASE::GetInterfaceFromGip(
  488. IWamRequest ** ppIWamRequest
  489. )
  490. {
  491. HRESULT hrRet = NOERROR;
  492. if ( m_gipIWamRequest == 0 ) {
  493. //
  494. // In low-memory, etc cases we may not have a gip cookie
  495. // (see bug 86872)
  496. //
  497. // We quote verbatim from raid:
  498. //
  499. /*
  500. this was the bug:
  501. - the call from WAM::ProcessRequest to InitWamExecInfo fails due to oom when
  502. calling GetCoreState (probably due to the allocation in the COM marshaler)
  503. - thus, _gipIWamRequest remains 0
  504. - we jump to failure code in WAM::ProcessRequest and call WAM_EXEC_INFO::
  505. PrepCleanupAndRelease
  506. - PrepCleanupAndRelease assert-failed because _gipIWamRequest == 0
  507. - after the asertion fialure we crash trying to call PrepCleanupWamRequest on
  508. a null ptr
  509. this is the fix:
  510. - in WAM_EXEC_INFO::PrepCleanupAndRelease we no longer assert, and now
  511. proactively avoid the cross-process call if _gipIWamRequest == 0
  512. additional robust-ification, related to the fix:
  513. - added fail-fast code to GetIWamRequest for the case _gipIWamRequest == 0 (
  514. replaces the assert stanley saw, above)
  515. - many more DBGPRINTFs in InitWamExecInfo and elsewhere
  516. */
  517. hrRet = E_FAIL;
  518. } else {
  519. DBG_ASSERT( AssertOopValid() );
  520. IF_DEBUG( WAM_THREADID ) {
  521. DBGPRINTF((
  522. DBG_CONTEXT
  523. , "WAM_EXEC_BASE(%08x)::GetInterfaceFromGip before gip.Get"
  524. "m_dwThreadIdISA(%d)"
  525. "\n"
  526. , this
  527. , m_dwThreadIdISA
  528. ));
  529. }
  530. //
  531. // Get a thread-valid ptr from gip-master
  532. //
  533. hrRet = g_GIPAPI.Get(
  534. m_gipIWamRequest
  535. , IID_IWamRequest
  536. , (void **) ppIWamRequest
  537. );
  538. IF_DEBUG( WAM_THREADID ) {
  539. DBGPRINTF((
  540. DBG_CONTEXT
  541. , "WAM_EXEC_BASE(%08x)::GetInterfaceFromGip after gip.Get "
  542. "m_dwThreadIdISA(%d)"
  543. "\n"
  544. , this
  545. , m_dwThreadIdISA
  546. ));
  547. if ( m_dwThreadIdISA == 0 ) {
  548. m_dwThreadIdISA = GetCurrentThreadId();
  549. DBGPRINTF((
  550. DBG_CONTEXT
  551. , "WAM_EXEC_BASE(%08x)::GetInterfaceFromGip "
  552. "after hokey debug refresh "
  553. "m_dwThreadIdISA(%d)"
  554. "\n"
  555. , this
  556. , m_dwThreadIdISA
  557. ));
  558. }
  559. }
  560. IF_DEBUG( WAM_THREADID ) {
  561. DBGPRINTF((
  562. DBG_CONTEXT
  563. , "WAM_EXEC_BASE(%08x)::GetInterfaceFromGip after CoUninitialize "
  564. "m_dwThreadIdISA(%d)"
  565. "\n"
  566. , this
  567. , m_dwThreadIdISA
  568. ));
  569. }
  570. IF_DEBUG( WAM_REFCOUNTS ) {
  571. if ( hrRet == NOERROR ) {
  572. DBGPRINTF((
  573. DBG_CONTEXT
  574. , "WAM_EXEC_BASE(%08x)::GetIWamRequest"
  575. "gets ptr %08x"
  576. "\n"
  577. , this
  578. , *ppIWamRequest
  579. ));
  580. } else {
  581. DBGPRINTF((
  582. DBG_CONTEXT
  583. , "WAM_EXEC_BASE(%08x)::GetIWamRequest failed "
  584. "hrRet(%08x) "
  585. "\n"
  586. , this
  587. , hrRet
  588. ));
  589. }
  590. }
  591. }
  592. return hrRet;
  593. }
  594. BOOL
  595. WAM_EXEC_BASE::AssertSmartISAValid()
  596. {
  597. IF_DEBUG( WAM_THREADID ) {
  598. DBGPRINTF((
  599. DBG_CONTEXT
  600. , "WAM_EXEC_BASE(%08x)::AssertSmartISAValid"
  601. "\n\t"
  602. "m_fInProcess(%d) "
  603. "m_pIWamReqInproc(%d) "
  604. "m_gipIWamRequest(%d) "
  605. "m_pIWamReqSmartISA(%d) "
  606. "\n\t"
  607. "m_dwThreadIdISA(%d) "
  608. "Current thread id(%d) "
  609. "\n"
  610. , this
  611. , m_fInProcess
  612. , m_pIWamReqInproc
  613. , m_gipIWamRequest
  614. , m_pIWamReqSmartISA
  615. , m_dwThreadIdISA
  616. , GetCurrentThreadId()
  617. ));
  618. }
  619. return(
  620. AssertOopValid()
  621. && m_pIWamReqSmartISA
  622. && m_dwThreadIdISA
  623. );
  624. }
  625. /************************ End of File *********************************/