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.

2986 lines
81 KiB

  1. /*===================================================================
  2. Microsoft Denali
  3. Microsoft Confidential.
  4. Copyright 1996 Microsoft Corporation. All Rights Reserved.
  5. Component: Main
  6. File: Hitobj.cpp
  7. Owner: DmitryR
  8. This file contains the CHitObj class implementation.
  9. ===================================================================*/
  10. #include "denpre.h"
  11. #pragma hdrstop
  12. #include "context.h"
  13. #include "exec.h"
  14. #include "mtacb.h"
  15. #include "perfdata.h"
  16. #include "debugger.h"
  17. #include "asperror.h"
  18. #include "thrdgate.h"
  19. #include "memchk.h"
  20. //resource failure globals
  21. #include "rfs.h"
  22. #ifdef _RFS
  23. MemRFS memrfs;
  24. #endif
  25. #ifdef SCRIPT_STATS
  26. # define REG_ASP_DEBUG_LOCATION "System\\CurrentControlSet\\Services\\W3Svc\\ASP"
  27. # define REG_STR_QUEUE_DEBUG_THRESHOLD "QueueDebugThreshold"
  28. # define REG_DEF_QUEUE_DEBUG_THRESHOLD 25
  29. DWORD g_dwQueueDebugThreshold = 0; // REG_DEF_QUEUE_DEBUG_THRESHOLD;
  30. # define REG_STR_SEND_SCRIPTLESS_ON_ATQ_THREAD "SendScriptlessOnAtqThread"
  31. # define REG_DEF_SEND_SCRIPTLESS_ON_ATQ_THREAD 1
  32. DWORD g_fSendScriptlessOnAtqThread = REG_DEF_SEND_SCRIPTLESS_ON_ATQ_THREAD;
  33. void
  34. ReadRegistrySettings()
  35. {
  36. HKEY hkey = NULL;
  37. DWORD dwErr = RegOpenKeyEx(HKEY_LOCAL_MACHINE, REG_ASP_DEBUG_LOCATION,
  38. 0, KEY_READ, &hkey);
  39. if (dwErr == NO_ERROR)
  40. {
  41. DWORD dwType, dwBuffer;
  42. DWORD cbBuffer = sizeof(dwBuffer);
  43. dwErr = RegQueryValueEx(hkey, REG_STR_QUEUE_DEBUG_THRESHOLD,
  44. NULL, &dwType, (LPBYTE) &dwBuffer, &cbBuffer);
  45. if (dwErr == NO_ERROR)
  46. g_dwQueueDebugThreshold = dwBuffer;
  47. dwErr = RegQueryValueEx(hkey, REG_STR_SEND_SCRIPTLESS_ON_ATQ_THREAD,
  48. NULL, &dwType, (LPBYTE) &dwBuffer, &cbBuffer);
  49. if (dwErr == NO_ERROR)
  50. g_fSendScriptlessOnAtqThread = dwBuffer;
  51. RegCloseKey(hkey);
  52. }
  53. char szTemp[200];
  54. sprintf(szTemp, "RRS, err = %d, QueueDebugThreshold = %d, SendScriptlessOnAtqThread = %d\n",
  55. dwErr, g_dwQueueDebugThreshold, g_fSendScriptlessOnAtqThread);
  56. OutputDebugString(szTemp);
  57. }
  58. CSmallSpinLock g_lockRequestStats;
  59. LONG g_cRequests = 0;
  60. LONG g_cScriptlessRequests = 0;
  61. LONG g_cHttpExtensionsExecuting = 0;
  62. LONG g_cConcurrentScriptlessRequests = 0;
  63. LONG g_cMaxConcurrentScriptlessRequests = 0;
  64. LONGLONG g_nSumConcurrentScriptlessRequests = 0;
  65. LONGLONG g_nSumExecTimeScriptlessRequests = 0;
  66. LONG g_nAvgConcurrentScriptlessRequests = 0;
  67. LONG g_nAvgExecTimeScriptlessRequests = 0;
  68. #endif // SCRIPT_STATS
  69. DWORD g_nBrowserRequests = 0;
  70. DWORD g_nSessionCleanupRequests = 0;
  71. DWORD g_nApplnCleanupRequests = 0;
  72. IGlobalInterfaceTable *g_pGIT = NULL;
  73. /*===================================================================
  74. CHitObj::CHitObj
  75. Constructor
  76. Parameters:
  77. NONE
  78. Returns:
  79. NONE
  80. ===================================================================*/
  81. CHitObj::CHitObj()
  82. : m_fInited(FALSE),
  83. m_ehtType(ehtUnInitedRequest),
  84. m_hImpersonate(hNil),
  85. m_pIReq(NULL),
  86. m_pResponse(NULL),
  87. m_pRequest(NULL),
  88. m_pServer(NULL),
  89. m_punkScriptingNamespace(NULL),
  90. m_dwObjectContextCookie(NULL_GIP_COOKIE),
  91. m_pPageCompCol(NULL),
  92. m_pPageObjMgr(NULL),
  93. m_pActivity(NULL),
  94. m_ecsActivityScope(csUnknown),
  95. m_SessionId(INVALID_ID, 0, 0),
  96. m_pSession(NULL),
  97. m_pAppln(NULL),
  98. m_fRunGlobalAsa(FALSE),
  99. m_fStartSession(FALSE),
  100. m_fNewCookie(FALSE),
  101. m_fStartApplication(FALSE),
  102. m_fApplnOnStartFailed(FALSE),
  103. m_fClientCodeDebug(FALSE),
  104. m_fCompilationFailed(FALSE),
  105. m_fExecuting(FALSE),
  106. m_fHideRequestAndResponseIntrinsics(FALSE),
  107. m_fHideSessionIntrinsic(FALSE),
  108. m_fDoneWithSession(FALSE),
  109. m_fRejected(FALSE),
  110. m_f449Done(FALSE),
  111. m_fInTransferOnError(FALSE),
  112. m_pScriptingContext(NULL),
  113. m_nScriptTimeout(0),
  114. m_eExecStatus(eExecSucceeded),
  115. m_eEventState(eEventNone),
  116. m_uCodePage(CP_ACP),
  117. m_lcid(LOCALE_SYSTEM_DEFAULT),
  118. m_dwtTimestamp(0),
  119. m_pEngineInfo(NULL),
  120. m_pdispTypeLibWrapper(NULL),
  121. m_szCurrTemplateVirtPath(NULL),
  122. m_szCurrTemplatePhysPath(NULL),
  123. m_pASPError(NULL),
  124. m_pTemplate(NULL),
  125. m_fSecure(FALSE)
  126. {
  127. }
  128. /*===================================================================
  129. CHitObj::~CHitObj
  130. Destructor
  131. Parameters:
  132. None
  133. Returns:
  134. None
  135. ===================================================================*/
  136. CHitObj::~CHitObj( void )
  137. {
  138. Assert(!m_fExecuting); // no deletes while still executing
  139. if (FIsBrowserRequest())
  140. {
  141. if (m_hImpersonate != hNil)
  142. m_hImpersonate = hNil;
  143. if (m_pSession)
  144. DetachBrowserRequestFromSession();
  145. }
  146. if (m_pASPError) // Error object
  147. {
  148. m_pASPError->Release();
  149. m_pASPError = NULL;
  150. }
  151. if (m_pActivity) // page-level Viper activity
  152. {
  153. delete m_pActivity;
  154. m_pActivity = NULL;
  155. }
  156. StopComponentProcessing();
  157. if (m_pdispTypeLibWrapper)
  158. m_pdispTypeLibWrapper->Release();
  159. // update request counters in application and session manager
  160. if (m_pAppln)
  161. {
  162. if (FIsBrowserRequest())
  163. {
  164. m_pAppln->DecrementRequestCount();
  165. }
  166. else if (FIsSessionCleanupRequest() && m_pAppln->PSessionMgr())
  167. {
  168. m_pAppln->PSessionMgr()->DecrementSessionCleanupRequestCount();
  169. }
  170. }
  171. if (m_pTemplate)
  172. m_pTemplate->Release();
  173. // update global request counters
  174. if (FIsBrowserRequest())
  175. InterlockedDecrement((LPLONG)&g_nBrowserRequests);
  176. else if (FIsSessionCleanupRequest())
  177. InterlockedDecrement((LPLONG)&g_nSessionCleanupRequests);
  178. else if (FIsApplnCleanupRequest())
  179. InterlockedDecrement((LPLONG)&g_nApplnCleanupRequests);
  180. if (m_pIReq)
  181. m_pIReq->Release();
  182. }
  183. /*===================================================================
  184. CHitObj::NewBrowserRequest
  185. Static method. Creates, Inits, Posts new browser request
  186. Parameters:
  187. pIReq CIsapiReqInfo
  188. pfRejected [out] TRUE if rejected (optional)
  189. pfCompeleted [out] TRUE if comleted (optional)
  190. piErrorId [out] error id (optional)
  191. Returns:
  192. S_OK on success
  193. E_FAIL on failure
  194. ===================================================================*/
  195. HRESULT CHitObj::NewBrowserRequest
  196. (
  197. CIsapiReqInfo *pIReq,
  198. BOOL *pfRejected,
  199. BOOL *pfCompleted,
  200. int *piErrorId
  201. )
  202. {
  203. HRESULT hr = S_OK;
  204. BOOL fRejected = FALSE;
  205. BOOL fCompleted = FALSE;
  206. int iError = 0;
  207. CHitObj *pHitObj = new CHitObj;
  208. if (!pHitObj)
  209. hr = E_OUTOFMEMORY;
  210. if (SUCCEEDED(hr))
  211. {
  212. // Bracket BrowserRequestInit
  213. if (SUCCEEDED(StartISAThreadBracket(pIReq)))
  214. {
  215. hr = pHitObj->BrowserRequestInit(pIReq, &iError);
  216. if (SUCCEEDED(hr))
  217. {
  218. if (pHitObj->FDoneWithSession())
  219. {
  220. // finished while on I/O thread
  221. fCompleted = TRUE;
  222. delete pHitObj;
  223. pHitObj = NULL;
  224. }
  225. }
  226. else // if FAILED
  227. {
  228. if (iError == IDE_SERVER_TOO_BUSY)
  229. fRejected = TRUE;
  230. }
  231. EndISAThreadBracket(pIReq);
  232. }
  233. else
  234. {
  235. hr = E_FAIL;
  236. }
  237. }
  238. // Post into Viper
  239. if (SUCCEEDED(hr) && !fCompleted)
  240. {
  241. hr = pHitObj->PostViperAsyncCall();
  242. if (FAILED(hr))
  243. fRejected = TRUE;
  244. }
  245. if (FAILED(hr) && pHitObj)
  246. {
  247. // Bracket HitObj destructor
  248. // This code is only executed if PostViperAsyncCall either
  249. // failed or was never called -- thus we don't worry about
  250. // everlapping bracketing with the worker thread.
  251. if (SUCCEEDED(StartISAThreadBracket(pIReq)))
  252. {
  253. pHitObj->m_fRejected = TRUE;
  254. delete pHitObj;
  255. EndISAThreadBracket(pIReq);
  256. }
  257. }
  258. if (pfRejected)
  259. *pfRejected = fRejected;
  260. if (pfCompleted)
  261. *pfCompleted = fCompleted;
  262. if (piErrorId)
  263. *piErrorId = iError;
  264. return hr;
  265. }
  266. /*===================================================================
  267. HRESULT CHitObj::SetCodePage
  268. Set Runtime CodePage, if fAllowSessionState is On, this will set
  269. Session.CodePage and we should always use Session.CodePage when we
  270. call HitObj.GetCodePage when fAllowSessionState on.
  271. HitObj.CodePage is only set when fAllowSessionState is off or
  272. ApplicationCleanup, because we don't have Session.CodePage anymore, session
  273. does not even exist.
  274. Parameters:
  275. UINT uCodePage
  276. Returns:
  277. S_OK on success
  278. E_FAIL on failure
  279. ===================================================================*/
  280. HRESULT CHitObj::SetCodePage(UINT uCodePage)
  281. {
  282. HRESULT hr = S_OK;
  283. if (uCodePage == CP_ACP || IsValidCodePage(uCodePage))
  284. {
  285. m_uCodePage = uCodePage;
  286. // If engine info is available, notify the scripts engines that the code
  287. // page has changed
  288. if (m_pEngineInfo)
  289. {
  290. for (int i = 0; i < m_pEngineInfo->cActiveEngines; i++)
  291. {
  292. Assert(m_pEngineInfo->rgActiveEngines[i].pScriptEngine != NULL);
  293. m_pEngineInfo->rgActiveEngines[i].pScriptEngine->UpdateLocaleInfo(hostinfoCodePage);
  294. }
  295. }
  296. return hr;
  297. }
  298. return E_FAIL;
  299. }
  300. /*===================================================================
  301. HRESULT CHitObj::SetLCID
  302. Set Runtime LCID, if fAllowSessionState is On, this will set
  303. Session.LCID and we should always use Session.LCID when we
  304. call HitObj.LCID when fAllowSessionState on.
  305. HitObj.LCID is only set when fAllowSessionState is off or
  306. ApplicationCleanup, because we don't have Session.CodePage anymore, session
  307. does not even exist.
  308. Parameters:
  309. LCID lcid
  310. Returns:
  311. S_OK on success
  312. E_FAIL on failure
  313. ===================================================================*/
  314. HRESULT CHitObj::SetLCID(LCID lcid)
  315. {
  316. HRESULT hr = S_OK;
  317. if ((LOCALE_SYSTEM_DEFAULT == lcid) || IsValidLocale(lcid, LCID_INSTALLED))
  318. {
  319. m_lcid = lcid;
  320. // If engine info is available, notify the scripts engines that the
  321. // lcid has changed
  322. if (m_pEngineInfo)
  323. {
  324. for (int i = 0; i < m_pEngineInfo->cActiveEngines; i++)
  325. {
  326. Assert(m_pEngineInfo->rgActiveEngines[i].pScriptEngine != NULL);
  327. m_pEngineInfo->rgActiveEngines[i].pScriptEngine->UpdateLocaleInfo(hostinfoLocale);
  328. }
  329. }
  330. return hr;
  331. }
  332. return E_FAIL;
  333. }
  334. /*===================================================================
  335. HRESULT CHitObj::BrowserRequestInit
  336. Initialize the request object
  337. Parameters:
  338. CIsapiReqInfo *pIReq
  339. int *pErrorId
  340. Returns:
  341. S_OK on success
  342. E_FAIL on failure
  343. ===================================================================*/
  344. HRESULT CHitObj::BrowserRequestInit
  345. (
  346. CIsapiReqInfo *pIReq,
  347. int *pErrorId
  348. )
  349. {
  350. HRESULT hr;
  351. m_pIReq = pIReq;
  352. m_pIReq->AddRef();
  353. m_ehtType = ehtBrowserRequest;
  354. InterlockedIncrement((LPLONG)&g_nBrowserRequests);
  355. #ifdef SCRIPT_STATS
  356. InterlockedIncrement(&g_cRequests);
  357. #endif // SCRIPT_STATS
  358. STACK_BUFFER( serverPortSecureBuff, 8 );
  359. DWORD cbServerPortSecure;
  360. if( !SERVER_GET (pIReq,"SERVER_PORT_SECURE", &serverPortSecureBuff, &cbServerPortSecure))
  361. {
  362. if (GetLastError() == E_OUTOFMEMORY)
  363. {
  364. return E_OUTOFMEMORY;
  365. }
  366. }
  367. char *szServerPortSecure = (char *)serverPortSecureBuff.QueryPtr();
  368. m_fSecure = (szServerPortSecure[0] == '1' );
  369. // Ask W3SVC for the impersonation token so we can later impersonate on Viper's thread
  370. if (FIsWinNT())
  371. m_hImpersonate = m_pIReq->QueryImpersonationToken();
  372. // Uppercase path - BUGBUG - can't Normalize in place!!!!
  373. Normalize(m_pIReq->QueryPszPathTranslated());
  374. // Reject direct requests for global.asa file
  375. if (FIsGlobalAsa(m_pIReq->QueryPszPathTranslated(), m_pIReq->QueryCchPathTranslated()))
  376. {
  377. *pErrorId = IDE_GLOBAL_ASA_FORBIDDEN;
  378. return E_FAIL;
  379. }
  380. // Create page component collection
  381. hr = InitComponentProcessing();
  382. if (FAILED(hr))
  383. {
  384. *pErrorId = (hr == E_OUTOFMEMORY) ? IDE_OOM : IDE_INIT_PAGE_LEVEL_OBJ;
  385. return hr;
  386. }
  387. // Attach to application (or create a new one)
  388. BOOL fApplnRestarting = FALSE;
  389. hr = AssignApplnToBrowserRequest(&fApplnRestarting);
  390. if (FAILED(hr))
  391. {
  392. *pErrorId = fApplnRestarting ? IDE_GLOBAL_ASA_CHANGED
  393. : IDE_ADD_APPLICATION;
  394. return E_FAIL;
  395. }
  396. // Get Session cookie, and misc flags from http header
  397. hr = ParseCookiesForSessionIdAndFlags();
  398. if (FAILED(hr)) // no cookie is not an error -- failed here means OOM
  399. return hr;
  400. // Remember script timeout value
  401. m_nScriptTimeout = m_pAppln->QueryAppConfig()->dwScriptTimeout();
  402. // Check if the session is needed
  403. BOOL fAllowSessions = m_pAppln->QueryAppConfig()->fAllowSessionState();
  404. BOOL fNeedSession = fAllowSessions;
  405. // Look if the template is cached
  406. CTemplate *pTemplate = NULL;
  407. // Find in cache - don't load if not in cache already
  408. hr = g_TemplateCache.FindCached
  409. (
  410. m_pIReq->QueryPszPathTranslated(),
  411. DWInstanceID(),
  412. &pTemplate
  413. );
  414. if (hr == S_OK)
  415. {
  416. Assert(pTemplate);
  417. // store the template away for later use...
  418. //pTemplate->AddRef();
  419. //m_pTemplate = pTemplate;
  420. if (fAllowSessions)
  421. {
  422. // check for session-less templates
  423. fNeedSession = pTemplate->FSession();
  424. }
  425. else
  426. {
  427. #ifdef SCRIPT_STATS
  428. if (pTemplate->FScriptless())
  429. InterlockedIncrement(&g_cScriptlessRequests);
  430. #endif // SCRIPT_STATS
  431. // check for scipt-less templates to be
  432. // completed on the I/O thread (when no debugging)
  433. if (
  434. #ifdef SCRIPT_STATS
  435. g_fSendScriptlessOnAtqThread &&
  436. #endif // SCRIPT_STATS
  437. pTemplate->FScriptless() && !m_pAppln->FDebuggable())
  438. {
  439. #ifdef SCRIPT_STATS
  440. LONG c = InterlockedIncrement(&g_cConcurrentScriptlessRequests);
  441. DWORD dwTime = GetTickCount();
  442. #endif // SCRIPT_STATS
  443. if (SUCCEEDED(CResponse::SyncWriteScriptlessTemplate(m_pIReq, pTemplate)))
  444. {
  445. #ifndef PERF_DISABLE
  446. g_PerfData.Incr_REQPERSEC();
  447. g_PerfData.Incr_REQSUCCEEDED();
  448. #endif
  449. m_fDoneWithSession = TRUE; // do not post to MTS
  450. }
  451. #ifdef SCRIPT_STATS
  452. dwTime = GetTickCount() - dwTime;
  453. InterlockedDecrement(&g_cConcurrentScriptlessRequests);
  454. g_lockRequestStats.WriteLock();
  455. g_nSumExecTimeScriptlessRequests += dwTime;
  456. if (c > g_cMaxConcurrentScriptlessRequests)
  457. g_cMaxConcurrentScriptlessRequests = c;
  458. g_nSumConcurrentScriptlessRequests += c;
  459. g_nAvgConcurrentScriptlessRequests = (LONG)
  460. (g_nSumConcurrentScriptlessRequests
  461. / g_cScriptlessRequests);
  462. g_nAvgExecTimeScriptlessRequests = (LONG)
  463. (g_nSumExecTimeScriptlessRequests
  464. / g_cScriptlessRequests);
  465. g_lockRequestStats.WriteUnlock();
  466. #endif // SCRIPT_STATS
  467. }
  468. }
  469. // When possible, generate 449 cookies while on I/O thread
  470. if (!m_fDoneWithSession)
  471. {
  472. if (!SUCCEEDED(pTemplate->Do449Processing(this)))
  473. g_TemplateCache.Flush(m_pIReq->QueryPszPathTranslated(), DWInstanceID());
  474. }
  475. pTemplate->Release();
  476. }
  477. // initialize CodePage and LCID to the app defaults...
  478. m_uCodePage = PAppln()->QueryAppConfig()->uCodePage();
  479. m_lcid = PAppln()->QueryAppConfig()->uLCID();
  480. if (!fNeedSession || m_fDoneWithSession)
  481. {
  482. m_fInited = TRUE;
  483. return S_OK;
  484. }
  485. // Attach to session or create a new one
  486. BOOL fNewSession, fNewCookie;
  487. hr = AssignSessionToBrowserRequest(&fNewSession, &fNewCookie, pErrorId);
  488. if (FAILED(hr))
  489. return E_FAIL;
  490. Assert(m_pSession);
  491. // Move from inside "if (fNewSesson)"
  492. if (fNewCookie)
  493. m_fNewCookie = TRUE;
  494. if (fNewSession)
  495. {
  496. m_fStartSession = TRUE;
  497. if (m_pAppln->FHasGlobalAsa())
  498. m_fRunGlobalAsa = TRUE;
  499. }
  500. m_fInited = TRUE;
  501. return S_OK;
  502. }
  503. /*===================================================================
  504. CHitObj::AssignApplnToBrowserRequest
  505. Find or create a new appln for this browser request
  506. Does the appln manager locking
  507. Parameters:
  508. pfApplnRestarting [out] flag - failed because the appln
  509. found is restarting
  510. Returns:
  511. HRESULT
  512. ===================================================================*/
  513. HRESULT CHitObj::AssignApplnToBrowserRequest
  514. (
  515. BOOL *pfApplnRestarting
  516. )
  517. {
  518. HRESULT hr;
  519. Assert(pfApplnRestarting);
  520. *pfApplnRestarting = FALSE;
  521. Assert(!m_pAppln);
  522. TCHAR *szAppMDPath = m_pIReq->QueryPszApplnMDPath();
  523. if (!szAppMDPath)
  524. return E_FAIL;
  525. // Lock the application manager
  526. g_ApplnMgr.Lock();
  527. // Find by application by metabase key
  528. CAppln *pAppln;
  529. hr = g_ApplnMgr.FindAppln(szAppMDPath, &pAppln);
  530. if (hr == S_OK)
  531. {
  532. // Reject requests for restarting applications
  533. if (pAppln->FGlobalChanged())
  534. {
  535. *pfApplnRestarting = TRUE;
  536. g_ApplnMgr.UnLock();
  537. return E_FAIL;
  538. }
  539. // Update appln config from metabase if needed
  540. else if (pAppln->FConfigNeedsUpdate())
  541. {
  542. // If debugging flag has changed, then restart the application
  543. BOOL fRestartAppln = FALSE;
  544. BOOL fFlushAll = FALSE;
  545. pAppln->UpdateConfig(m_pIReq, &fRestartAppln, &fFlushAll);
  546. if (fRestartAppln)
  547. {
  548. pAppln->Restart(TRUE); // force a restart
  549. pAppln = NULL;
  550. if (fFlushAll) // flush all can only happen when restart is TRUE
  551. {
  552. // do flush while unlocked
  553. g_ApplnMgr.UnLock();
  554. g_TemplateCache.FlushAll();
  555. g_ApplnMgr.Lock();
  556. }
  557. // Find again
  558. hr = g_ApplnMgr.FindAppln(szAppMDPath, &pAppln);
  559. // Reject if still restarting
  560. if (hr == S_OK && pAppln->FGlobalChanged())
  561. {
  562. *pfApplnRestarting = TRUE;
  563. g_ApplnMgr.UnLock();
  564. return E_FAIL;
  565. }
  566. }
  567. else
  568. {
  569. // adjust sctipt killer timeout
  570. g_ScriptManager.AdjustScriptKillerTimeout
  571. (
  572. // application timeout / 2 (in ms)
  573. pAppln->QueryAppConfig()->dwScriptTimeout() * 500
  574. );
  575. }
  576. }
  577. }
  578. if (hr != S_OK) // Application NOT found
  579. {
  580. TCHAR *szAppPhysicalPath = GetSzAppPhysicalPath();
  581. if (!szAppPhysicalPath)
  582. {
  583. g_ApplnMgr.UnLock();
  584. return E_FAIL;
  585. }
  586. // try to create a new one
  587. hr = g_ApplnMgr.AddAppln
  588. (
  589. szAppMDPath, // metabase key
  590. szAppPhysicalPath,
  591. m_pIReq,
  592. m_hImpersonate,
  593. &pAppln
  594. );
  595. if (FAILED(hr))
  596. {
  597. g_ApplnMgr.UnLock();
  598. free (szAppPhysicalPath);
  599. return hr;
  600. }
  601. // Check for GLOBAL.ASA
  602. TCHAR szGlobalAsaPath[MAX_PATH*2];
  603. DWORD cchPath = _tcslen(szAppPhysicalPath);
  604. _tcscpy(szGlobalAsaPath, szAppPhysicalPath);
  605. // BUG FIX: 102010 DBCS code fixes
  606. //if (szGlobalAsaPath[cchPath-1] != '\\')
  607. if ( *CharPrev(szGlobalAsaPath, szGlobalAsaPath + cchPath) != _T('\\'))
  608. szGlobalAsaPath[cchPath++] = _T('\\');
  609. _tcscpy(szGlobalAsaPath+cchPath, SZ_GLOBAL_ASA);
  610. // Check if GLOBAL.ASA exists
  611. BOOL fGlobalAsaExists = FALSE;
  612. if (SUCCEEDED(AspGetFileAttributes(szGlobalAsaPath)))
  613. {
  614. fGlobalAsaExists = TRUE;
  615. }
  616. else if (GetLastError() == ERROR_ACCESS_DENIED)
  617. {
  618. // If the current user doesn't have access (could happen when
  619. // there's an ACL on directory) try under SYSTEM user
  620. if (m_hImpersonate)
  621. {
  622. RevertToSelf();
  623. if (SUCCEEDED(AspGetFileAttributes(szGlobalAsaPath)))
  624. fGlobalAsaExists = TRUE;
  625. HANDLE hThread = GetCurrentThread();
  626. SetThreadToken(&hThread, m_hImpersonate);
  627. }
  628. }
  629. if (fGlobalAsaExists)
  630. pAppln->SetGlobalAsa(szGlobalAsaPath);
  631. // Start monitoring application directory to
  632. // catch changes to GLOBAL.ASA even if it's not there
  633. if (FIsWinNT())
  634. {
  635. g_FileAppMap.AddFileApplication(szGlobalAsaPath, pAppln);
  636. CASPDirMonitorEntry *pDME = NULL;
  637. if (RegisterASPDirMonitorEntry(szAppPhysicalPath, &pDME, TRUE))
  638. pAppln->AddDirMonitorEntry(pDME);
  639. }
  640. free(szAppPhysicalPath);
  641. szAppPhysicalPath = NULL;
  642. // Update config from registry - don't care about restart
  643. // application is fresh baked
  644. pAppln->UpdateConfig(m_pIReq);
  645. // Adjust script killer timeout to current application
  646. g_ScriptManager.AdjustScriptKillerTimeout
  647. (
  648. // application timeout / 2 (in ms)
  649. pAppln->QueryAppConfig()->dwScriptTimeout() * 500
  650. );
  651. }
  652. // We have an application at this point
  653. Assert(pAppln);
  654. m_pAppln = pAppln;
  655. // Increment request count before releasing ApplMgr lock
  656. // to make sure it will not remove the app from under us
  657. m_pAppln->IncrementRequestCount();
  658. // Unlock the application manager
  659. g_ApplnMgr.UnLock();
  660. return S_OK;
  661. }
  662. /*===================================================================
  663. CHitObj::AssignSessionToBrowserRequest
  664. Find or create a new session for this browser request
  665. Does the session manager locking
  666. Parameters:
  667. pfNewSession [out] flag - new session created
  668. pfNewCookie [out] flag - new cookie crated
  669. pErrorId [out] -- error ID if failed
  670. Returns:
  671. HRESULT
  672. ===================================================================*/
  673. HRESULT CHitObj::AssignSessionToBrowserRequest
  674. (
  675. BOOL *pfNewSession,
  676. BOOL *pfNewCookie,
  677. int *pErrorId
  678. )
  679. {
  680. Assert(pfNewSession);
  681. Assert(pfNewCookie);
  682. Assert(!m_pSession);
  683. // Local vars
  684. BOOL fTooManySessions = FALSE;
  685. BOOL fUseNewSession = FALSE;
  686. BOOL fUseOldSession = FALSE;
  687. BOOL fUseNewCookie = FALSE;
  688. CSession *pNewSession = NULL; // newly created
  689. CSession *pOldSession = NULL; // existing session that is found
  690. BOOL fReuseIdAndCookie = FALSE;
  691. BOOL fValidId = g_SessionIdGenerator.IsValidId(m_SessionId.m_dwId);
  692. HRESULT hr = S_OK;
  693. CSessionMgr *pSessionMgr = m_pAppln->PSessionMgr();
  694. while (1)
  695. {
  696. // Try to find session by Id
  697. if (fValidId)
  698. {
  699. pSessionMgr->LockMaster();
  700. pOldSession = NULL;
  701. HRESULT hrFind = pSessionMgr->FindInMasterHash
  702. (
  703. m_SessionId,
  704. &pOldSession
  705. );
  706. // Good old Session?
  707. if (hrFind == NOERROR) // QFE has this condition as hrFind == NOERROR
  708. {
  709. Assert(pOldSession);
  710. // If AspKeepSessionIDSecure is set in metabase and
  711. // they are going from a nonsecure to a secure connection then
  712. // transition the user from their old http sessionid to their
  713. // new https secure session id
  714. if (QueryAppConfig()->fKeepSessionIDSecure() &&
  715. FSecure() &&
  716. !pOldSession->FSecureSession()
  717. )
  718. {
  719. // Generate New Cookie
  720. hr = pSessionMgr->GenerateIdAndCookie
  721. (
  722. &m_SessionId,
  723. m_szSessionCookie
  724. );
  725. if (SUCCEEDED(hr))
  726. {
  727. hr = pSessionMgr->ChangeSessionId(pOldSession,m_SessionId);
  728. }
  729. if (FAILED(hr))
  730. {
  731. pSessionMgr->UnLockMaster();
  732. break;
  733. }
  734. pOldSession->SetSecureSession(TRUE);
  735. fUseNewCookie = TRUE;
  736. }
  737. // Increment request count before unlock to avoid
  738. // deletion of the session by other threads
  739. pOldSession->IncrementRequestsCount();
  740. pSessionMgr->UnLockMaster();
  741. fUseOldSession = TRUE;
  742. break;
  743. }
  744. // Bad old Session?
  745. else if (pOldSession)
  746. {
  747. pSessionMgr->UnLockMaster();
  748. fValidId = FALSE;
  749. }
  750. // No old session and we have a new session to insert?
  751. else if (pNewSession)
  752. {
  753. hr = pSessionMgr->AddToMasterHash(pNewSession);
  754. if (SUCCEEDED(hr))
  755. {
  756. // Increment request count before unlock to avoid
  757. // deletion of the session by other threads
  758. pNewSession->IncrementRequestsCount();
  759. fUseNewSession = TRUE;
  760. }
  761. pSessionMgr->UnLockMaster();
  762. break;
  763. }
  764. // No old session and no new session
  765. else
  766. {
  767. pSessionMgr->UnLockMaster();
  768. if (FSecure () && QueryAppConfig()->fKeepSessionIDSecure())
  769. {
  770. fValidId = FALSE;
  771. }
  772. }
  773. }
  774. // Generate id and cookie when needed
  775. if (!fValidId) // 2nd time generate new id
  776. {
  777. hr = pSessionMgr->GenerateIdAndCookie
  778. (
  779. &m_SessionId,
  780. m_szSessionCookie
  781. );
  782. if (FAILED(hr))
  783. break;
  784. fValidId = TRUE;
  785. fUseNewCookie = TRUE;
  786. }
  787. // Create new session object if needed
  788. if (!pNewSession)
  789. {
  790. // Enforce the session limit for the application
  791. DWORD dwSessionLimit = m_pAppln->QueryAppConfig()->dwSessionMax();
  792. if (dwSessionLimit != 0xffffffff && dwSessionLimit != 0 &&
  793. m_pAppln->GetNumSessions() >= dwSessionLimit)
  794. {
  795. fTooManySessions = TRUE;
  796. hr = E_FAIL;
  797. break;
  798. }
  799. hr = pSessionMgr->NewSession(m_SessionId, &pNewSession);
  800. if (FAILED(hr))
  801. break;
  802. }
  803. else
  804. {
  805. // Assign new id to already created new session
  806. pNewSession->AssignNewId(m_SessionId);
  807. }
  808. // continue with the loop
  809. }
  810. // the results
  811. if (fUseNewSession)
  812. {
  813. Assert(SUCCEEDED(hr));
  814. Assert(pNewSession);
  815. m_pSession = pNewSession;
  816. m_pSession->SetSecureSession(FSecure());
  817. pNewSession = NULL; // not to be deleted later
  818. }
  819. else if (fUseOldSession)
  820. {
  821. Assert(SUCCEEDED(hr));
  822. Assert(pOldSession);
  823. m_pSession = pOldSession;
  824. }
  825. else
  826. {
  827. Assert(FAILED(hr));
  828. *pErrorId = fTooManySessions ? IDE_TOO_MANY_USERS : IDE_ADD_SESSION;
  829. }
  830. // cleanup new session if unused
  831. if (pNewSession)
  832. {
  833. pNewSession->UnInit();
  834. pNewSession->Release();
  835. pNewSession = NULL;
  836. }
  837. if (m_pSession && m_pSession->FCodePageSet()) {
  838. m_uCodePage = m_pSession->GetCodePage();
  839. }
  840. else {
  841. m_uCodePage = PAppln()->QueryAppConfig()->uCodePage();
  842. }
  843. if (m_pSession && m_pSession->FLCIDSet()) {
  844. m_lcid = m_pSession->GetLCID();
  845. }
  846. else {
  847. m_lcid = PAppln()->QueryAppConfig()->uLCID();
  848. }
  849. // return flags
  850. *pfNewSession = fUseNewSession;
  851. *pfNewCookie = fUseNewCookie;
  852. return hr;
  853. }
  854. /*===================================================================
  855. CHitObj::DetachBrowserRequestFromSession
  856. Removes session from browser request.
  857. Does session clean-up when needed
  858. Parameters:
  859. Returns:
  860. HRESULT
  861. ===================================================================*/
  862. HRESULT CHitObj::DetachBrowserRequestFromSession()
  863. {
  864. Assert(m_pSession);
  865. Assert(m_pSession->PAppln());
  866. if (IsShutDownInProgress() || m_pSession->FInTOBucket())
  867. {
  868. // nothing fancy on shutdown
  869. // or if the session is still in the timeout bucket
  870. // (could happen for rejected requests)
  871. m_pSession->DecrementRequestsCount();
  872. m_pSession = NULL;
  873. return S_OK;
  874. }
  875. CSessionMgr *pSessionMgr = m_pSession->PAppln()->PSessionMgr();
  876. Assert(pSessionMgr);
  877. // try to delete this session if this is the last pending request
  878. if (m_pSession->GetRequestsCount() == 1)
  879. {
  880. // convert to lightweight if possible
  881. m_pSession->MakeLightWeight();
  882. // check if need to delete now
  883. if (m_pSession->FShouldBeDeletedNow(TRUE))
  884. {
  885. pSessionMgr->LockMaster();
  886. // check if still need to delete now after locking
  887. if (m_pSession->FShouldBeDeletedNow(TRUE))
  888. {
  889. pSessionMgr->RemoveFromMasterHash(m_pSession);
  890. pSessionMgr->UnLockMaster();
  891. m_pSession->DecrementRequestsCount();
  892. pSessionMgr->DeleteSession(m_pSession, TRUE);
  893. m_pSession = NULL;
  894. return S_OK;
  895. }
  896. pSessionMgr->UnLockMaster();
  897. }
  898. }
  899. // We can end up here for a rejected requests only if there are
  900. // other (non-rejected) requests for this session.
  901. //
  902. // The category of rejected here does not include rejected because
  903. // of the RequestQueueMax. This only applies to real OOM situations.
  904. //
  905. // In case of rejected request or if there are other pending
  906. // requests for this, session these other requests will take
  907. // care of reinserting the session into the timeout bucket.
  908. //
  909. // Rejected requests are NOT serialized -- they don't run on Viper
  910. // threads. Inserting the session into a timeout bucket for a
  911. // rejected request might create a race condition with regular requests.
  912. if (!m_fRejected && m_pSession->GetRequestsCount() == 1)
  913. {
  914. // Insert into proper timeout bucket
  915. if (pSessionMgr->FIsSessionKillerScheduled())
  916. {
  917. pSessionMgr->UpdateSessionTimeoutTime(m_pSession);
  918. pSessionMgr->AddSessionToTOBucket(m_pSession);
  919. }
  920. }
  921. m_pSession->DecrementRequestsCount();
  922. // session is no longer attached to the request
  923. m_pSession = NULL;
  924. return S_OK;
  925. }
  926. /*===================================================================
  927. void CHitObj::SessionCleanupInit
  928. Initialize a request object for session cleanup
  929. Parameters:
  930. CSession *pSession Session object context
  931. Returns:
  932. NONE
  933. ===================================================================*/
  934. void CHitObj::SessionCleanupInit
  935. (
  936. CSession * pSession
  937. )
  938. {
  939. m_ehtType = ehtSessionCleanup;
  940. InterlockedIncrement((LPLONG)&g_nSessionCleanupRequests);
  941. HRESULT hr = InitComponentProcessing();
  942. if (FAILED(hr))
  943. {
  944. if (hr == E_OUTOFMEMORY)
  945. HandleOOMError(NULL, NULL);
  946. }
  947. m_pSession = pSession;
  948. m_pAppln = pSession->PAppln();
  949. m_fRunGlobalAsa = TRUE;
  950. m_pIReq = NULL;
  951. if (m_pAppln->PSessionMgr())
  952. m_pAppln->PSessionMgr()->IncrementSessionCleanupRequestCount();
  953. m_fInited = TRUE;
  954. }
  955. /*===================================================================
  956. void CHitObj::ApplicationCleanupInit
  957. Initializes a request object for application cleanup
  958. Parameters:
  959. CAppln * pAppln Application object context
  960. Returns:
  961. NONE
  962. ===================================================================*/
  963. void CHitObj::ApplicationCleanupInit( CAppln * pAppln )
  964. {
  965. m_ehtType = ehtApplicationCleanup;
  966. InterlockedIncrement((LPLONG)&g_nApplnCleanupRequests);
  967. // If OOM here, then cleanup request does not get a server object.
  968. HRESULT hr = InitComponentProcessing();
  969. if (FAILED(hr))
  970. {
  971. if (hr == E_OUTOFMEMORY)
  972. HandleOOMError(NULL, NULL);
  973. }
  974. m_pAppln = pAppln;
  975. m_fRunGlobalAsa = TRUE;
  976. m_pIReq = NULL;
  977. m_fInited = TRUE;
  978. }
  979. /*===================================================================
  980. CHitObj::ReassignAbandonedSession
  981. Reassign ID of a the session being abandonded thus
  982. detaching it from the client
  983. Parameters:
  984. Returns:
  985. HRESULT
  986. ===================================================================*/
  987. HRESULT CHitObj::ReassignAbandonedSession()
  988. {
  989. HRESULT hr = E_FAIL;
  990. Assert(m_pSession);
  991. Assert(m_pAppln);
  992. m_pAppln->AssertValid();
  993. hr = m_pAppln->PSessionMgr()->GenerateIdAndCookie
  994. (
  995. &m_SessionId,
  996. m_szSessionCookie
  997. );
  998. if (SUCCEEDED(hr))
  999. {
  1000. hr = m_pAppln->PSessionMgr()->ChangeSessionId
  1001. (
  1002. m_pSession,
  1003. m_SessionId
  1004. );
  1005. }
  1006. return hr;
  1007. }
  1008. /*===================================================================
  1009. void CHitObj::FObjectTag
  1010. Check if the object passed in as argument is an object tag
  1011. created object.
  1012. Parameters:
  1013. IDispatch * pDispatch pointer to object
  1014. Returns:
  1015. TRUE Is a object tag created object
  1016. FALSE Otherwise
  1017. ===================================================================*/
  1018. BOOL CHitObj::FObjectTag( IDispatch * pDispatch )
  1019. {
  1020. if (!m_pPageObjMgr)
  1021. return FALSE;
  1022. BOOL fRet = TRUE;
  1023. CComponentObject *pObj = NULL;
  1024. HRESULT hr = m_pPageObjMgr->
  1025. FindAnyScopeComponentByIDispatch(pDispatch, &pObj);
  1026. return (SUCCEEDED(hr) && pObj);
  1027. }
  1028. /* buffer allows space for: <user cookie> + CCH_SESSION_ID_COOKIE + = + <cookie> + '\0')
  1029. 50 + 20 + 1 + SESSIONID_LEN + 1
  1030. NOTE we arbitrarily allow 50 bytes for <user cookie>
  1031. NOTE if CCH_SESSION_ID_COOKIE changes, CCH_BUFCOOKIES_DEFAULT must be changed accordingly
  1032. */
  1033. #define CCH_BUFCOOKIES_DEFAULT 72 + SESSIONID_LEN
  1034. /*===================================================================
  1035. CHitObj::ParseCookiesForSessionIdAndFlags
  1036. Extracts Cookie from CIsapiReqInfo.
  1037. Parameters:
  1038. Side Effects:
  1039. Initializes m_SessionId, m_SessionIdR1, m_SessionIdR2 and
  1040. m_szSessionCookie
  1041. Sets m_fClientCodeDebug flag
  1042. Returns:
  1043. S_OK Extracted cookie value successfully
  1044. S_FALSE Success, but no cookie found
  1045. other error
  1046. ===================================================================*/
  1047. HRESULT CHitObj::ParseCookiesForSessionIdAndFlags()
  1048. {
  1049. Assert(m_pAppln);
  1050. CAppConfig *pAppConfig = m_pAppln->QueryAppConfig();
  1051. // Are we interested in ANY cookies?
  1052. if (!pAppConfig->fAllowSessionState() &&
  1053. !pAppConfig->fAllowClientDebug())
  1054. return S_OK;
  1055. // If session cookie is needed init it
  1056. if (pAppConfig->fAllowSessionState())
  1057. {
  1058. m_SessionId.m_dwId = INVALID_ID;
  1059. m_szSessionCookie[0] = '\0';
  1060. }
  1061. // Get cookies from WAM_EXEC_INFO
  1062. char *szBufCookies = m_pIReq->QueryPszCookie();
  1063. if (!szBufCookies || !*szBufCookies)
  1064. return S_OK; // no cookies
  1065. // Obtain Session Cookie (and ID) if needed
  1066. if (pAppConfig->fAllowSessionState())
  1067. {
  1068. char *pT;
  1069. if (pT = strstr(szBufCookies, g_szSessionIDCookieName))
  1070. {
  1071. pT += CCH_SESSION_ID_COOKIE;
  1072. if (*pT == '=')
  1073. {
  1074. pT++;
  1075. if (strlen( pT ) >= SESSIONID_LEN)
  1076. {
  1077. memcpy(m_szSessionCookie, pT, SESSIONID_LEN);
  1078. m_szSessionCookie[SESSIONID_LEN] = '\0';
  1079. }
  1080. }
  1081. }
  1082. // validate and try to decode the session id cookie
  1083. if (m_szSessionCookie[0] != '\0')
  1084. {
  1085. if (FAILED(DecodeSessionIdCookie
  1086. (
  1087. m_szSessionCookie,
  1088. &m_SessionId.m_dwId,
  1089. &m_SessionId.m_dwR1,
  1090. &m_SessionId.m_dwR2
  1091. )))
  1092. {
  1093. m_SessionId.m_dwId = INVALID_ID;
  1094. m_szSessionCookie[0] = '\0';
  1095. }
  1096. }
  1097. }
  1098. // Look for Client Debug enabling cookie
  1099. if (pAppConfig->fAllowClientDebug())
  1100. {
  1101. if (strstr(szBufCookies, SZ_CLIENT_DEBUG_COOKIE"="))
  1102. m_fClientCodeDebug = TRUE;
  1103. }
  1104. return S_OK;
  1105. }
  1106. /*===================================================================
  1107. BOOL CHitObj::GetSzAppPhysicalPath
  1108. Extracts application directory from WAM_EXEC_INFO
  1109. Parameters:
  1110. Side Effects:
  1111. On success, allocate memory for pszAppPhysicalPath
  1112. Returns:
  1113. TRUE AppPhysicalPath
  1114. FALSE NULL
  1115. ===================================================================*/
  1116. TCHAR *CHitObj::GetSzAppPhysicalPath()
  1117. {
  1118. DWORD dwSizeofBuffer = 265*sizeof(TCHAR);
  1119. TCHAR *pszAppPhysicalPathLocal = (TCHAR *)malloc(dwSizeofBuffer);
  1120. CHAR *pszApplPhysPathVarName;
  1121. if (!pszAppPhysicalPathLocal)
  1122. return NULL;
  1123. #if UNICODE
  1124. pszApplPhysPathVarName = "UNICODE_APPL_PHYSICAL_PATH";
  1125. #else
  1126. pszApplPhysPathVarName = "APPL_PHYSICAL_PATH";
  1127. #endif
  1128. BOOL fFound = m_pIReq->GetServerVariable
  1129. (
  1130. pszApplPhysPathVarName,
  1131. pszAppPhysicalPathLocal,
  1132. &dwSizeofBuffer
  1133. );
  1134. if (!fFound)
  1135. {
  1136. DWORD dwErr = GetLastError();
  1137. if (ERROR_INSUFFICIENT_BUFFER == dwErr)
  1138. {
  1139. // Not Enough Buffer
  1140. free(pszAppPhysicalPathLocal);
  1141. pszAppPhysicalPathLocal = (TCHAR *)malloc(dwSizeofBuffer);
  1142. if (pszAppPhysicalPathLocal)
  1143. {
  1144. // Try again
  1145. fFound = m_pIReq->GetServerVariable
  1146. (
  1147. pszApplPhysPathVarName,
  1148. pszAppPhysicalPathLocal,
  1149. &dwSizeofBuffer
  1150. );
  1151. }
  1152. }
  1153. }
  1154. if (!fFound) {
  1155. if (pszAppPhysicalPathLocal) {
  1156. free(pszAppPhysicalPathLocal);
  1157. pszAppPhysicalPathLocal = NULL;
  1158. }
  1159. }
  1160. else
  1161. {
  1162. Assert(pszAppPhysicalPathLocal);
  1163. Normalize(pszAppPhysicalPathLocal);
  1164. }
  1165. return pszAppPhysicalPathLocal;
  1166. }
  1167. /*===================================================================
  1168. CHitObj::InitComponentProcessing
  1169. Creates and inits component collection and page object manager
  1170. Parameters:
  1171. Returns:
  1172. HRESULT
  1173. ===================================================================*/
  1174. HRESULT CHitObj::InitComponentProcessing()
  1175. {
  1176. Assert(!m_pPageCompCol);
  1177. Assert(!m_pPageObjMgr);
  1178. HRESULT hr = S_OK;
  1179. // Page component collection
  1180. m_pPageCompCol = new CComponentCollection;
  1181. if (!m_pPageCompCol)
  1182. return E_OUTOFMEMORY;
  1183. hr = m_pPageCompCol->Init(csPage);
  1184. if (FAILED(hr))
  1185. return hr;
  1186. // Page object manager
  1187. m_pPageObjMgr = new CPageComponentManager;
  1188. if (!m_pPageObjMgr)
  1189. return E_OUTOFMEMORY;
  1190. hr = m_pPageObjMgr->Init(this);
  1191. if (FAILED(hr))
  1192. return hr;
  1193. return S_OK;
  1194. }
  1195. /*===================================================================
  1196. CHitObj::StopComponentProcessing
  1197. Deletes component collection and page object manager
  1198. Parameters:
  1199. Returns:
  1200. HRESULT
  1201. ===================================================================*/
  1202. HRESULT CHitObj::StopComponentProcessing()
  1203. {
  1204. if (m_pPageObjMgr)
  1205. {
  1206. delete m_pPageObjMgr;
  1207. m_pPageObjMgr = NULL;
  1208. }
  1209. if (m_pPageCompCol)
  1210. {
  1211. delete m_pPageCompCol;
  1212. m_pPageCompCol = NULL;
  1213. }
  1214. if (m_punkScriptingNamespace)
  1215. {
  1216. m_punkScriptingNamespace->Release();
  1217. m_punkScriptingNamespace = NULL;
  1218. }
  1219. if (m_dwObjectContextCookie != NULL_GIP_COOKIE)
  1220. {
  1221. RemoveObjectContext();
  1222. }
  1223. return S_OK;
  1224. }
  1225. /*===================================================================
  1226. CHitObj::GetPageComponentCollection
  1227. Returns component collection for page
  1228. Parameters:
  1229. CComponentCollection **ppCollection output
  1230. Returns:
  1231. HRESULT
  1232. ===================================================================*/
  1233. HRESULT CHitObj::GetPageComponentCollection
  1234. (
  1235. CComponentCollection **ppCollection
  1236. )
  1237. {
  1238. *ppCollection = m_pPageCompCol;
  1239. return (*ppCollection) ? S_OK : TYPE_E_ELEMENTNOTFOUND;
  1240. }
  1241. /*===================================================================
  1242. CHitObj::GetSessionComponentCollection
  1243. Returns component collection for session
  1244. Parameters:
  1245. CComponentCollection **ppCollection output
  1246. Returns:
  1247. HRESULT
  1248. ===================================================================*/
  1249. HRESULT CHitObj::GetSessionComponentCollection
  1250. (
  1251. CComponentCollection **ppCollection
  1252. )
  1253. {
  1254. if (m_pSession)
  1255. {
  1256. *ppCollection = m_pSession->PCompCol();
  1257. if (*ppCollection == NULL && // no collection
  1258. m_eEventState != eEventAppOnStart && // not an application
  1259. m_eEventState != eEventAppOnEnd) // level event
  1260. {
  1261. // init session collection on demand
  1262. HRESULT hr = m_pSession->CreateComponentCollection();
  1263. if (SUCCEEDED(hr))
  1264. *ppCollection = m_pSession->PCompCol();
  1265. }
  1266. }
  1267. else
  1268. *ppCollection = NULL;
  1269. return (*ppCollection) ? S_OK : TYPE_E_ELEMENTNOTFOUND;
  1270. }
  1271. /*===================================================================
  1272. CHitObj::GetApplnComponentCollection
  1273. Returns component collection for application
  1274. Parameters:
  1275. CComponentCollection **ppCollection output
  1276. Returns:
  1277. HRESULT
  1278. ===================================================================*/
  1279. HRESULT CHitObj::GetApplnComponentCollection
  1280. (
  1281. CComponentCollection **ppCollection
  1282. )
  1283. {
  1284. if (m_pAppln)
  1285. *ppCollection = m_pAppln->PCompCol();
  1286. else
  1287. *ppCollection = NULL;
  1288. return (*ppCollection) ? S_OK : TYPE_E_ELEMENTNOTFOUND;
  1289. }
  1290. /*===================================================================
  1291. CHitObj::AddComponent
  1292. Adds uninstantiated tagged object to appropriate
  1293. component collection
  1294. Parameters:
  1295. CompType type
  1296. const CLSID &clsid
  1297. CompScope scope
  1298. CompModel model
  1299. LPWSTR pwszName
  1300. IUnknown *pUnk
  1301. Returns:
  1302. HRESULT
  1303. ===================================================================*/
  1304. HRESULT CHitObj::AddComponent
  1305. (
  1306. CompType type,
  1307. const CLSID &clsid,
  1308. CompScope scope,
  1309. CompModel model,
  1310. LPWSTR pwszName,
  1311. IUnknown *pUnk
  1312. )
  1313. {
  1314. Assert(m_pPageObjMgr);
  1315. m_pPageObjMgr->AssertValid();
  1316. Assert(type == ctTagged);
  1317. HRESULT hr = m_pPageObjMgr->AddScopedTagged
  1318. (
  1319. scope,
  1320. pwszName,
  1321. clsid,
  1322. model
  1323. );
  1324. return hr;
  1325. }
  1326. /*===================================================================
  1327. CHitObj::GetComponent
  1328. Finds CComponentObject by scope and name
  1329. Parameters:
  1330. CompScope scope can be csUnknown
  1331. LPWSTR pwszName name to find
  1332. DWORD cbName name length (in bytes)
  1333. CComponentObject **ppObj (out) object found
  1334. Returns:
  1335. HRESULT S_OK on success
  1336. TYPE_E_ELEMENTNOTFOUND if the object wasnt found
  1337. Other HRESULT if object fails to instantiate
  1338. ===================================================================*/
  1339. HRESULT CHitObj::GetComponent
  1340. (
  1341. CompScope scope,
  1342. LPWSTR pwszName,
  1343. DWORD cbName,
  1344. CComponentObject **ppObj
  1345. )
  1346. {
  1347. Assert(ppObj);
  1348. *ppObj = NULL;
  1349. if (!m_pPageObjMgr)
  1350. return TYPE_E_ELEMENTNOTFOUND;
  1351. BOOL fNewInstance = FALSE;
  1352. HRESULT hr = m_pPageObjMgr->GetScopedObjectInstantiated
  1353. (
  1354. scope,
  1355. pwszName,
  1356. cbName,
  1357. ppObj,
  1358. &fNewInstance
  1359. );
  1360. if (FAILED(hr))
  1361. return hr;
  1362. // If an object that restricts threading has been instantiateed
  1363. // as the session's tagged <OBJECT>, and the session's activity
  1364. // runs this request, then bind the session's activity to thread
  1365. if ((*ppObj)->GetScope() == csSession && // session scope component
  1366. m_ecsActivityScope == csSession && // session scope activity
  1367. SUCCEEDED(hr) && // get object succeeded
  1368. fNewInstance && // object was just instantiated
  1369. *ppObj && !(*ppObj)->FAgile()) // the object is thread-locked
  1370. {
  1371. m_pSession->PActivity()->BindToThread();
  1372. }
  1373. return hr;
  1374. }
  1375. /*===================================================================
  1376. CHitObj::GetIntrinsic
  1377. Finds Intrinsic by name
  1378. Parameters:
  1379. LPWSTR pwszName name to find
  1380. DWORD cbName name length (in bytes)
  1381. IUnknown **ppUnk (out) object found
  1382. Returns:
  1383. HRESULT S_OK on success
  1384. S_FALSE name of the instrinsic but it's missing
  1385. TYPE_E_ELEMENTNOTFOUND if the object not found
  1386. ===================================================================*/
  1387. HRESULT CHitObj::GetIntrinsic
  1388. (
  1389. LPWSTR pwszName,
  1390. DWORD cbName,
  1391. IUnknown **ppUnk
  1392. )
  1393. {
  1394. Assert(ppUnk);
  1395. *ppUnk = NULL;
  1396. // Lookup table based on (wszName[0] - cbName) % 32
  1397. // Works for both uppper and lower case names
  1398. static enum IntrinsicType
  1399. {
  1400. itUnknown = 0,
  1401. itObjContext,
  1402. itNamespace,
  1403. itAppln,
  1404. itSession,
  1405. itRequest,
  1406. itResponse,
  1407. itServer,
  1408. itASPPageTLB,
  1409. itASPGlobalTLB
  1410. }
  1411. rgitLookupEntries[] =
  1412. {
  1413. /* 0-1 */ itUnknown, itUnknown,
  1414. /* 2 */ itResponse,
  1415. /* 3 */ itUnknown,
  1416. /* 4 */ itRequest,
  1417. /* 5 */ itSession,
  1418. /* 6 */ itUnknown,
  1419. /* 7 */ itServer,
  1420. /* 8 */ itUnknown,
  1421. /* 9 */ itASPGlobalTLB,
  1422. /* 10 */ itUnknown,
  1423. /* 11 */ itAppln,
  1424. /* 12 */ itUnknown,
  1425. /* 13 */ itASPPageTLB,
  1426. /* 14 */ itUnknown,
  1427. /* 15 */ itNamespace,
  1428. /* 16-20 */ itUnknown, itUnknown, itUnknown, itUnknown, itUnknown,
  1429. /* 21 */ itObjContext,
  1430. /* 22-31 */ itUnknown, itUnknown, itUnknown, itUnknown, itUnknown,
  1431. itUnknown, itUnknown, itUnknown, itUnknown, itUnknown
  1432. };
  1433. IntrinsicType itType = rgitLookupEntries
  1434. [
  1435. (pwszName[0] - cbName) & 0x1f // &1f same as %32
  1436. ];
  1437. if (itType == itUnknown) // most likely
  1438. return TYPE_E_ELEMENTNOTFOUND;
  1439. // Do the string comparison
  1440. BOOL fNameMatch = FALSE;
  1441. switch (itType)
  1442. {
  1443. case itNamespace:
  1444. if (_wcsicmp(pwszName, WSZ_OBJ_SCRIPTINGNAMESPACE) == 0)
  1445. {
  1446. fNameMatch = TRUE;
  1447. *ppUnk = m_punkScriptingNamespace;
  1448. }
  1449. break;
  1450. case itResponse:
  1451. if (_wcsicmp(pwszName, WSZ_OBJ_RESPONSE) == 0)
  1452. {
  1453. fNameMatch = TRUE;
  1454. if (!m_fHideRequestAndResponseIntrinsics)
  1455. *ppUnk = static_cast<IResponse *>(m_pResponse);
  1456. }
  1457. break;
  1458. case itRequest:
  1459. if (_wcsicmp(pwszName, WSZ_OBJ_REQUEST) == 0)
  1460. {
  1461. fNameMatch = TRUE;
  1462. if (!m_fHideRequestAndResponseIntrinsics)
  1463. *ppUnk = static_cast<IRequest *>(m_pRequest);
  1464. }
  1465. break;
  1466. case itSession:
  1467. if (_wcsicmp(pwszName, WSZ_OBJ_SESSION) == 0)
  1468. {
  1469. fNameMatch = TRUE;
  1470. if (!m_fHideSessionIntrinsic)
  1471. *ppUnk = static_cast<ISessionObject *>(m_pSession);
  1472. }
  1473. break;
  1474. case itServer:
  1475. if (_wcsicmp(pwszName, WSZ_OBJ_SERVER) == 0)
  1476. {
  1477. fNameMatch = TRUE;
  1478. *ppUnk = static_cast<IServer *>(m_pServer);
  1479. }
  1480. break;
  1481. case itAppln:
  1482. if (_wcsicmp(pwszName, WSZ_OBJ_APPLICATION) == 0)
  1483. {
  1484. fNameMatch = TRUE;
  1485. *ppUnk = static_cast<IApplicationObject *>(m_pAppln);
  1486. }
  1487. break;
  1488. case itObjContext:
  1489. if (_wcsicmp(pwszName, WSZ_OBJ_OBJECTCONTEXT) == 0)
  1490. {
  1491. IASPObjectContext* pASPObjectContext = NULL;
  1492. // WARNING. We're making two assumptions here. First, we
  1493. // assume that the GIT holds a reference to the object.
  1494. // Second, we assume that this script runs in the context
  1495. // that owns the object, so, the release won't destroy a
  1496. // proxy or anything. The problem is, the code we're
  1497. // replacing counted on the reference passed back to the
  1498. // script was also held here. There's obviously nobody
  1499. // "up there" that's releasing it, so, we have to do it
  1500. // here to simulate the old code.
  1501. UseObjectContext(&pASPObjectContext);
  1502. if (pASPObjectContext == NULL)
  1503. {
  1504. Assert (FALSE);
  1505. return E_FAIL; // should never happen...
  1506. }
  1507. *ppUnk = pASPObjectContext;
  1508. pASPObjectContext->Release();
  1509. fNameMatch = TRUE;
  1510. }
  1511. break;
  1512. case itASPPageTLB:
  1513. if (_wcsicmp(pwszName, WSZ_OBJ_ASPPAGETLB) == 0)
  1514. {
  1515. fNameMatch = TRUE;
  1516. *ppUnk = m_pdispTypeLibWrapper;
  1517. }
  1518. break;
  1519. case itASPGlobalTLB:
  1520. if (_wcsicmp(pwszName, WSZ_OBJ_ASPGLOBALTLB) == 0)
  1521. {
  1522. fNameMatch = TRUE;
  1523. *ppUnk = m_pAppln->PGlobTypeLibWrapper();
  1524. }
  1525. break;
  1526. }
  1527. if (*ppUnk) return S_OK;
  1528. else if (fNameMatch) return S_FALSE;
  1529. else return TYPE_E_ELEMENTNOTFOUND;
  1530. }
  1531. /*===================================================================
  1532. CHitObj::CreateComponent
  1533. Server.CreateObject calls this
  1534. Parameters:
  1535. clsid create of this CLSID
  1536. ppDisp return IDispatch*
  1537. Returns:
  1538. HRESULT
  1539. ===================================================================*/
  1540. HRESULT CHitObj::CreateComponent
  1541. (
  1542. const CLSID &clsid,
  1543. IDispatch **ppDisp
  1544. )
  1545. {
  1546. Assert(m_pPageObjMgr);
  1547. CComponentObject *pObj = NULL;
  1548. HRESULT hr = m_pPageObjMgr->AddScopedUnnamedInstantiated
  1549. (
  1550. csPage,
  1551. clsid,
  1552. cmUnknown,
  1553. NULL,
  1554. &pObj
  1555. );
  1556. if (FAILED(hr))
  1557. {
  1558. *ppDisp = NULL;
  1559. return hr;
  1560. }
  1561. Assert(pObj);
  1562. hr = pObj->GetAddRefdIDispatch(ppDisp);
  1563. if (SUCCEEDED(hr))
  1564. {
  1565. // don't keep the object around unless needed
  1566. if (pObj->FEarlyReleaseAllowed())
  1567. m_pPageObjMgr->RemoveComponent(pObj);
  1568. }
  1569. return hr;
  1570. }
  1571. /*===================================================================
  1572. CHitObj::SetPropertyComponent
  1573. Sets property value to variant
  1574. Parameters:
  1575. CompScope scope property scope
  1576. LPWSTR pwszName property name
  1577. VARIANT pVariant property value to set
  1578. Returns:
  1579. HRESULT
  1580. ===================================================================*/
  1581. HRESULT CHitObj::SetPropertyComponent
  1582. (
  1583. CompScope scope,
  1584. LPWSTR pwszName,
  1585. VARIANT *pVariant
  1586. )
  1587. {
  1588. if (!m_pPageObjMgr)
  1589. return TYPE_E_ELEMENTNOTFOUND;
  1590. CComponentObject *pObj = NULL;
  1591. HRESULT hr = m_pPageObjMgr->AddScopedProperty(scope, pwszName,
  1592. pVariant, &pObj);
  1593. // If an object that restricts threading has been assigned as
  1594. // the session property, and the session's activity runs this
  1595. // request, then bind the session's activity to thread
  1596. if (scope == csSession && // session scope property
  1597. m_ecsActivityScope == csSession && // session scope activity
  1598. SUCCEEDED(hr) && // set property succeed
  1599. pObj && !pObj->FAgile()) // the object is thread-locked
  1600. {
  1601. m_pSession->PActivity()->BindToThread();
  1602. }
  1603. return hr;
  1604. }
  1605. /*===================================================================
  1606. CHitObj::GetPropertyComponent
  1607. Finds property CComponentObject by scope and name
  1608. Parameters:
  1609. CompScope scope wher to find
  1610. LPWSTR pwszName name to find
  1611. CComponentObject **ppObj (out) object found
  1612. Returns:
  1613. HRESULT S_OK on success
  1614. TYPE_E_ELEMENTNOTFOUND if the object wasnt found
  1615. Other HRESULT
  1616. ===================================================================*/
  1617. HRESULT CHitObj::GetPropertyComponent
  1618. (
  1619. CompScope scope,
  1620. LPWSTR pwszName,
  1621. CComponentObject **ppObj
  1622. )
  1623. {
  1624. *ppObj = NULL;
  1625. if (!m_pPageObjMgr)
  1626. return TYPE_E_ELEMENTNOTFOUND;
  1627. return m_pPageObjMgr->GetScopedProperty(scope, pwszName, ppObj);
  1628. }
  1629. /*===================================================================
  1630. CHitObj::SetActivity
  1631. Remember activity with CHitObj
  1632. Parameters
  1633. CViperActivity *pActivity Viper activity to remember
  1634. (and later delete)
  1635. Returns:
  1636. HRESULT
  1637. ===================================================================*/
  1638. HRESULT CHitObj::SetActivity
  1639. (
  1640. CViperActivity *pActivity
  1641. )
  1642. {
  1643. Assert(!m_pActivity);
  1644. m_pActivity = pActivity;
  1645. return S_OK;
  1646. }
  1647. /*===================================================================
  1648. CHitObj::PCurrentActivity
  1649. Returns Viper Activity, the current HitObj is running under
  1650. Parameters
  1651. Returns:
  1652. CViperActivity *
  1653. ===================================================================*/
  1654. CViperActivity *CHitObj::PCurrentActivity()
  1655. {
  1656. CViperActivity *pActivity = NULL;
  1657. switch (m_ecsActivityScope)
  1658. {
  1659. case csPage:
  1660. pActivity = m_pActivity;
  1661. break;
  1662. case csSession:
  1663. Assert(m_pSession);
  1664. pActivity = m_pSession->PActivity();
  1665. break;
  1666. case csAppln:
  1667. Assert(m_pAppln);
  1668. pActivity = m_pAppln->PActivity();
  1669. break;
  1670. }
  1671. return pActivity;
  1672. }
  1673. /*===================================================================
  1674. CHitObj::PostViperAsyncCall
  1675. Asks Viper to calls us back from the right thread to execute
  1676. the request.
  1677. Used instead of queueing
  1678. Returns:
  1679. HRESULT
  1680. Side effects:
  1681. ===================================================================*/
  1682. HRESULT CHitObj::PostViperAsyncCall()
  1683. {
  1684. #ifndef PERF_DISABLE
  1685. BOOL fDecrOnFail = FALSE;
  1686. if (FIsBrowserRequest())
  1687. {
  1688. DWORD dwRequestQueued = g_PerfData.Incr_REQCURRENT();
  1689. #if 0 && defined(SCRIPT_STATS)
  1690. if (g_dwQueueDebugThreshold != 0
  1691. && dwRequestQueued >= g_dwQueueDebugThreshold)
  1692. DebugBreak();
  1693. #endif
  1694. fDecrOnFail = TRUE;
  1695. }
  1696. #endif
  1697. UpdateTimestamp(); // before posting into queue
  1698. CViperActivity *pApplnAct = m_pAppln ?
  1699. m_pAppln->PActivity() : NULL;
  1700. CViperActivity *pSessnAct = m_pSession ?
  1701. m_pSession->PActivity() : NULL;
  1702. HRESULT hr;
  1703. if (pApplnAct)
  1704. {
  1705. m_ecsActivityScope = csAppln;
  1706. hr = pApplnAct->PostAsyncRequest(this);
  1707. }
  1708. else if (pSessnAct)
  1709. {
  1710. m_ecsActivityScope = csSession;
  1711. hr = pSessnAct->PostAsyncRequest(this);
  1712. }
  1713. else
  1714. {
  1715. m_ecsActivityScope = csPage;
  1716. hr = CViperActivity::PostGlobalAsyncRequest(this);
  1717. }
  1718. #ifndef PERF_DISABLE
  1719. if (FAILED(hr) && fDecrOnFail)
  1720. g_PerfData.Decr_REQCURRENT();
  1721. #endif
  1722. return hr;
  1723. }
  1724. /*===================================================================
  1725. CHitObj::ViperAsyncCallback
  1726. Viper calls us back from the right thread to execute
  1727. the request.
  1728. Used instead of queueing
  1729. Parameters
  1730. BOOL *pfRePosted [out] flag TRUE if request re-posted
  1731. under diff activity (don't delete it)
  1732. Returns:
  1733. HRESULT
  1734. Side effects:
  1735. ===================================================================*/
  1736. HRESULT CHitObj::ViperAsyncCallback
  1737. (
  1738. BOOL *pfRePosted
  1739. )
  1740. {
  1741. HRESULT hr = S_OK;
  1742. BOOL fTemplateInCache;
  1743. *pfRePosted = FALSE;
  1744. Assert(!m_fExecuting); // no nested executions of the same request
  1745. m_fExecuting = TRUE;
  1746. Assert(FIsValidRequestType());
  1747. DWORD dwtWaitTime = ElapsedTimeSinceTimestamp();
  1748. UpdateTimestamp(); // received from the queue
  1749. #ifndef PERF_DISABLE
  1750. if (FIsBrowserRequest())
  1751. {
  1752. g_PerfData.Decr_REQCURRENT();
  1753. g_PerfData.Set_REQWAITTIME(dwtWaitTime);
  1754. }
  1755. #endif
  1756. ///////////////////
  1757. // Reject browser requests in certain situations
  1758. if (FIsBrowserRequest())
  1759. {
  1760. BOOL fRejected = FALSE;
  1761. RejectBrowserRequestWhenNeeded(dwtWaitTime, &fRejected);
  1762. if (fRejected)
  1763. return S_OK;
  1764. }
  1765. ///////////////////
  1766. // Pass through the thread gate
  1767. EnterThreadGate(m_dwtTimestamp);
  1768. ///////////////////
  1769. // Reject browser requests in certain situations
  1770. if (FIsBrowserRequest() && IsShutDownInProgress())
  1771. {
  1772. BOOL fRejected = FALSE;
  1773. RejectBrowserRequestWhenNeeded(dwtWaitTime, &fRejected);
  1774. if (fRejected)
  1775. return S_OK;
  1776. }
  1777. ///////////////////
  1778. // Remove the session from it's timeout bucket
  1779. // while executing the request
  1780. if (m_pSession && m_pSession->FInTOBucket())
  1781. m_pAppln->PSessionMgr()->RemoveSessionFromTOBucket(m_pSession);
  1782. ///////////////////
  1783. // If there's an application level activity we need to make
  1784. // sure this activity is bound to a thread. Could not bind it
  1785. // before because it has to be Viper thread to bind to.
  1786. CViperActivity *pApplnActivity = m_pAppln->PActivity();
  1787. if (pApplnActivity && !pApplnActivity->FThreadBound())
  1788. pApplnActivity->BindToThread();
  1789. ///////////////////
  1790. // Take care of first application request with GLOBAL.ASA
  1791. // Lock application if needed
  1792. BOOL fApplnLocked = FALSE;
  1793. BOOL fFirstAppRequest = FALSE;
  1794. if (FIsBrowserRequest() && m_pAppln->FHasGlobalAsa() &&
  1795. !m_pAppln->FFirstRequestRun())
  1796. {
  1797. m_pAppln->InternalLock();
  1798. fApplnLocked = TRUE;
  1799. if (!m_pAppln->FFirstRequestRun())
  1800. {
  1801. m_fStartApplication = TRUE;
  1802. m_fRunGlobalAsa = TRUE;
  1803. fFirstAppRequest = TRUE;
  1804. }
  1805. else
  1806. {
  1807. m_pAppln->InternalUnLock();
  1808. fApplnLocked = FALSE;
  1809. }
  1810. }
  1811. ///////////////////
  1812. // Repost under a different activity if needed
  1813. // (do it only after the first app request finished)
  1814. if (!fApplnLocked) // if not processing first app request
  1815. {
  1816. CViperActivity *pSessnAct, *pApplnAct;
  1817. CViperActivity *pRepostToActivity = NULL;
  1818. switch (m_ecsActivityScope)
  1819. {
  1820. case csPage:
  1821. // repost to session activity if any
  1822. pSessnAct = m_pSession ? m_pSession->PActivity() : NULL;
  1823. if (pSessnAct)
  1824. pRepostToActivity = pSessnAct;
  1825. // no break;
  1826. case csSession:
  1827. // repost to application activity if any
  1828. pApplnAct = m_pAppln ? m_pAppln->PActivity() : NULL;
  1829. if (pApplnAct)
  1830. pRepostToActivity = pApplnAct;
  1831. // no break;
  1832. case csAppln:
  1833. // never repost application activity request
  1834. break;
  1835. }
  1836. if (pRepostToActivity)
  1837. {
  1838. LeaveThreadGate(); // notify the thead gate
  1839. m_fExecuting = FALSE; // before reposting to avoid nesting
  1840. hr = pRepostToActivity->PostAsyncRequest(this);
  1841. *pfRePosted = SUCCEEDED(hr);
  1842. return hr;
  1843. }
  1844. }
  1845. ///////////////////
  1846. // Cleanup any scripting engines that need to be shut
  1847. // down on this thread, if we are on a thread enabled
  1848. // for debugging
  1849. if (m_pAppln->FDebuggable() && FIsBrowserRequest())
  1850. {
  1851. Assert(m_ecsActivityScope == csAppln);
  1852. g_ApplnMgr.CleanupEngines();
  1853. if (!g_dwDebugThreadId)
  1854. g_dwDebugThreadId = GetCurrentThreadId();
  1855. }
  1856. ///////////////////
  1857. // Prepare intrinsics
  1858. CIntrinsicObjects intrinsics;
  1859. m_pServer = NULL;
  1860. m_pResponse = NULL;
  1861. m_pRequest = NULL;
  1862. m_fHideRequestAndResponseIntrinsics = FALSE;
  1863. m_fHideSessionIntrinsic = FALSE;
  1864. m_punkScriptingNamespace = NULL;
  1865. m_dwObjectContextCookie = NULL_GIP_COOKIE;
  1866. hr = intrinsics.Prepare(m_pSession);
  1867. if (FAILED(hr)) // couldn't setup intrinsics
  1868. {
  1869. if (fApplnLocked)
  1870. m_pAppln->InternalUnLock();
  1871. #ifndef PERF_DISABLE
  1872. g_PerfData.Incr_REQFAILED();
  1873. g_PerfData.Incr_REQERRORPERSEC();
  1874. #endif
  1875. LeaveThreadGate(); // notify the thead gate
  1876. m_fExecuting = FALSE;
  1877. if (FIsBrowserRequest())
  1878. ReportServerError(IDE_SERVER_TOO_BUSY);
  1879. return hr;
  1880. }
  1881. if (FIsBrowserRequest())
  1882. {
  1883. m_pResponse = intrinsics.PResponse();
  1884. m_pRequest = intrinsics.PRequest();
  1885. }
  1886. m_pServer = intrinsics.PServer();
  1887. Assert(!FIsBrowserRequest() || m_pResponse);
  1888. ///////////////////
  1889. // Point session to this hit object
  1890. if (m_pSession)
  1891. m_pSession->SetHitObj(this);
  1892. ///////////////////
  1893. // Impersonate
  1894. HANDLE hThread = GetCurrentThread();
  1895. if (FIsBrowserRequest())
  1896. {
  1897. if (FIsWinNT())
  1898. {
  1899. if (!SetThreadToken(&hThread, m_hImpersonate))
  1900. {
  1901. #ifdef DBG
  1902. // for debug purposes, it is interesting to know what the error was
  1903. DWORD err = GetLastError();
  1904. #endif
  1905. ReportServerError(IDE_IMPERSONATE_USER);
  1906. m_eExecStatus = eExecFailed;
  1907. hr = E_FAIL;
  1908. }
  1909. }
  1910. }
  1911. ///////////////////
  1912. // Make Scripting Context
  1913. if (SUCCEEDED(hr))
  1914. {
  1915. Assert(!m_pScriptingContext);
  1916. m_pScriptingContext = new CScriptingContext
  1917. (
  1918. m_pAppln,
  1919. m_pSession,
  1920. m_pRequest,
  1921. m_pResponse,
  1922. m_pServer
  1923. );
  1924. if (!m_pScriptingContext)
  1925. hr = E_OUTOFMEMORY;
  1926. }
  1927. ///////////////////
  1928. // Attach to Viper context flow
  1929. if (SUCCEEDED(hr))
  1930. {
  1931. hr = ViperAttachIntrinsicsToContext
  1932. (
  1933. m_pAppln,
  1934. m_pSession,
  1935. m_pRequest,
  1936. m_pResponse,
  1937. m_pServer
  1938. );
  1939. }
  1940. ///////////////////
  1941. // Execute
  1942. BOOL fSkipExecute = FALSE; // (need to skip if session-less)
  1943. if (SUCCEEDED(hr))
  1944. {
  1945. CTemplate *pTemplate = NULL;
  1946. if (FIsBrowserRequest())
  1947. {
  1948. #ifndef PERF_DISABLE
  1949. g_PerfData.Incr_REQBROWSEREXEC();
  1950. #endif
  1951. // Init Response and Server for compiler errors
  1952. m_pResponse->ReInit(m_pIReq, NULL, m_pRequest, NULL, NULL, this);
  1953. m_pRequest->ReInit(m_pIReq, this);
  1954. m_pServer->ReInit(m_pIReq, this);
  1955. // Load the script - cache will AddRef
  1956. hr = LoadTemplate(m_pIReq->QueryPszPathTranslated(), this,
  1957. &pTemplate, intrinsics,
  1958. FALSE /* !GlobalAsa */, &fTemplateInCache);
  1959. // In case of ACL on the file (or directory) make sure
  1960. // we don't assume that AppOnStart succeeded on the
  1961. // first try (without the correct impersonation). Setting
  1962. // m_fApplnOnStartFailed will force another try, with the
  1963. // correct impersonation.
  1964. if (fFirstAppRequest && FAILED(hr))
  1965. m_fApplnOnStartFailed = TRUE;
  1966. // Take care of is session-less templates
  1967. if (SUCCEEDED(hr) && !pTemplate->FSession())
  1968. {
  1969. // UNDONE - Remove the reposting logic. Bug 301311.
  1970. //
  1971. // The problem is that we will leak the wam request and
  1972. // cause all sorts of trouble with keep alives. It seems
  1973. // like a marginal cost to just allow the first request to
  1974. // run on the session activity. We could also remove the
  1975. // StartISAThreadBracket restriction on nesting, but that
  1976. // seems like it might open up the door to making some
  1977. // real errors.
  1978. /*
  1979. // The problem only occurs the first time the
  1980. // template is loaded. After that there's a
  1981. // look-ahead in BrowserRequestInit()
  1982. // if the template wasn't cached before we could
  1983. // be running on session activity
  1984. if (m_ecsActivityScope == csSession)
  1985. {
  1986. // Repost with it's own activity
  1987. hr = NewBrowserRequest(m_pIReq);
  1988. fSkipExecute = TRUE;
  1989. // Mark this request as DONE_WITH_SESSION so that
  1990. // it will not be forced later. We don't need it
  1991. // because we posted another HitObj with the
  1992. // same WAM_EXEC_INFO
  1993. m_fDoneWithSession = TRUE;
  1994. }
  1995. else
  1996. */
  1997. if (m_pSession)
  1998. {
  1999. // Activity is alright (most likely
  2000. // application level) but still there's
  2001. // a session attached -> hide it
  2002. m_fHideSessionIntrinsic = TRUE;
  2003. }
  2004. }
  2005. // Take care of the 449 processing (most likely already done on I/O thread)
  2006. if (SUCCEEDED(hr) && !m_fDoneWithSession)
  2007. {
  2008. pTemplate->Do449Processing(this);
  2009. if (m_fDoneWithSession)
  2010. fSkipExecute = TRUE; // 449 sent the response
  2011. }
  2012. }
  2013. if (SUCCEEDED(hr) && !fSkipExecute)
  2014. {
  2015. // Execute script
  2016. MFS_START(memrfs)
  2017. hr = Execute(pTemplate, this, intrinsics);
  2018. MFS_END_HR(memrfs)
  2019. // OnEndPage
  2020. if (m_pPageObjMgr)
  2021. m_pPageObjMgr->OnEndPageAllObjects();
  2022. }
  2023. // Release the template
  2024. if (pTemplate)
  2025. pTemplate->Release();
  2026. if (FIsBrowserRequest())
  2027. {
  2028. if (!fSkipExecute)
  2029. {
  2030. // Flush response after completing execution
  2031. m_pResponse->FinalFlush(hr);
  2032. }
  2033. #ifndef PERF_DISABLE
  2034. g_PerfData.Decr_REQBROWSEREXEC();
  2035. #endif
  2036. }
  2037. else if (FIsSessionCleanupRequest())
  2038. {
  2039. // Remove session
  2040. if (m_pSession)
  2041. {
  2042. m_pSession->UnInit();
  2043. m_pSession->Release();
  2044. m_pSession = NULL;
  2045. }
  2046. }
  2047. else if (FIsApplnCleanupRequest())
  2048. {
  2049. // Remove application
  2050. if ( m_pAppln )
  2051. {
  2052. m_pAppln->UnInit();
  2053. m_pAppln->Release();
  2054. m_pAppln = NULL;
  2055. }
  2056. }
  2057. }
  2058. ///////////////////
  2059. // Release Scripting Context
  2060. if (m_pScriptingContext)
  2061. {
  2062. m_pScriptingContext->Release();
  2063. m_pScriptingContext = NULL;
  2064. }
  2065. ///////////////////
  2066. // Do The Perf Counters
  2067. #ifndef PERF_DISABLE
  2068. DWORD dwtExecTime = ElapsedTimeSinceTimestamp();
  2069. if (!fSkipExecute && FIsBrowserRequest())
  2070. {
  2071. g_PerfData.Incr_REQPERSEC();
  2072. g_PerfData.Set_REQEXECTIME(dwtExecTime);
  2073. switch (m_eExecStatus)
  2074. {
  2075. case eExecSucceeded:
  2076. if (m_pResponse->FWriteClientError())
  2077. {
  2078. g_PerfData.Incr_REQCOMFAILED();
  2079. g_PerfData.Incr_REQERRORPERSEC();
  2080. }
  2081. else
  2082. {
  2083. g_PerfData.Incr_REQSUCCEEDED();
  2084. }
  2085. break;
  2086. case eExecFailed:
  2087. if (hr == E_USER_LACKS_PERMISSIONS)
  2088. {
  2089. g_PerfData.Incr_REQNOTAUTH();
  2090. }
  2091. else if (FIsPreprocessorError(hr))
  2092. {
  2093. g_PerfData.Incr_REQERRPREPROC();
  2094. }
  2095. else if (m_fCompilationFailed)
  2096. {
  2097. g_PerfData.Incr_REQERRCOMPILE();
  2098. }
  2099. else
  2100. {
  2101. g_PerfData.Incr_REQERRRUNTIME();
  2102. }
  2103. g_PerfData.Incr_REQFAILED();
  2104. g_PerfData.Incr_REQERRORPERSEC();
  2105. break;
  2106. case eExecTimedOut:
  2107. g_PerfData.Incr_REQTIMEOUT();
  2108. break;
  2109. }
  2110. }
  2111. #endif
  2112. ///////////////////
  2113. // Cleanup after first application request
  2114. if (fFirstAppRequest && !m_fApplnOnStartFailed && !fSkipExecute)
  2115. m_pAppln->SetFirstRequestRan();
  2116. if (fApplnLocked)
  2117. m_pAppln->InternalUnLock();
  2118. ///////////////////
  2119. // make sure script didn't leave application locked
  2120. if (!FIsApplnCleanupRequest())
  2121. m_pAppln->UnLockAfterRequest();
  2122. ///////////////////
  2123. // In order not to refer to intrinsics later
  2124. // remove page component collection
  2125. StopComponentProcessing();
  2126. // Unset the impersonation
  2127. if (FIsWinNT())
  2128. SetThreadToken(&hThread, NULL);
  2129. ///////////////////
  2130. // Point session to NULL HitObj
  2131. if (m_pSession)
  2132. m_pSession->SetHitObj(NULL);
  2133. LeaveThreadGate(); // notify the thead gate
  2134. m_fExecuting = FALSE;
  2135. return hr;
  2136. }
  2137. /*===================================================================
  2138. CHitObj::ExecuteChildRequest
  2139. Executes child browser request
  2140. Parameters:
  2141. fTransfer -- flag -- End execution after this
  2142. szTemplate -- filename of the template to execute
  2143. szVirtTemplate -- virt path to template
  2144. Returns:
  2145. S_OK
  2146. ===================================================================*/
  2147. HRESULT CHitObj::ExecuteChildRequest
  2148. (
  2149. BOOL fTransfer,
  2150. TCHAR *szTemplate,
  2151. TCHAR *szVirtTemplate
  2152. )
  2153. {
  2154. HRESULT hr = S_OK;
  2155. // Prepare the new intrinsics structure (with the new scripting namespace)
  2156. CIntrinsicObjects intrinsics;
  2157. intrinsics.PrepareChild(m_pResponse, m_pRequest, m_pServer);
  2158. TCHAR *saved_m_szCurrTemplateVirtPath = m_szCurrTemplateVirtPath;
  2159. TCHAR *saved_m_szCurrTemplatePhysPath = m_szCurrTemplatePhysPath;
  2160. // these two fields used for compilation and error reporting
  2161. m_szCurrTemplateVirtPath = szVirtTemplate;
  2162. m_szCurrTemplatePhysPath = szTemplate;
  2163. // Load the template from cache
  2164. CTemplate *pTemplate = NULL;
  2165. BOOL fTemplateInCache;
  2166. hr = g_TemplateCache.Load(FALSE, szTemplate, DWInstanceID(), this, &pTemplate, &fTemplateInCache);
  2167. if (FAILED(hr))
  2168. {
  2169. if (pTemplate)
  2170. {
  2171. pTemplate->Release();
  2172. pTemplate = NULL;
  2173. }
  2174. m_szCurrTemplateVirtPath = saved_m_szCurrTemplateVirtPath;
  2175. m_szCurrTemplatePhysPath = saved_m_szCurrTemplatePhysPath;
  2176. // to tell the server object to display the correct error message
  2177. return E_COULDNT_OPEN_SOURCE_FILE;
  2178. }
  2179. // Save HitObj's execution state info
  2180. CComponentCollection *saved_m_pPageCompCol = m_pPageCompCol;
  2181. CPageComponentManager *saved_m_pPageObjMgr = m_pPageObjMgr;
  2182. IUnknown *saved_m_punkScriptingNamespace = m_punkScriptingNamespace;
  2183. DWORD saved_m_dwObjectContextCookie = m_dwObjectContextCookie;
  2184. ActiveEngineInfo *saved_m_pEngineInfo = m_pEngineInfo;
  2185. IDispatch *saved_m_pdispTypeLibWrapper = m_pdispTypeLibWrapper;
  2186. CTemplate *saved_pTemplate = m_pResponse->SwapTemplate(pTemplate);
  2187. void *saved_pvEngineInfo = m_pResponse->SwapScriptEngineInfo(NULL);
  2188. // Re-Init the saved state
  2189. m_pPageCompCol = NULL;
  2190. m_pPageObjMgr = NULL;
  2191. m_punkScriptingNamespace = NULL;
  2192. m_dwObjectContextCookie = NULL_GIP_COOKIE;
  2193. m_pEngineInfo = NULL;
  2194. m_pdispTypeLibWrapper = NULL;
  2195. // Create child request components framework
  2196. hr = InitComponentProcessing();
  2197. // Execute
  2198. if (SUCCEEDED(hr))
  2199. {
  2200. // Set status code to 500 in error cases.
  2201. if (FHasASPError())
  2202. m_pResponse->put_Status(L"500 Internal Server Error");
  2203. // Execute [child] script
  2204. hr = ::Execute(pTemplate, this, intrinsics, TRUE);
  2205. // OnEndPage
  2206. if (m_pPageObjMgr)
  2207. m_pPageObjMgr->OnEndPageAllObjects();
  2208. }
  2209. // Clean-out new components framework
  2210. StopComponentProcessing();
  2211. // Restore HitObj's execution state info
  2212. m_pPageCompCol = saved_m_pPageCompCol;
  2213. m_pPageObjMgr = saved_m_pPageObjMgr;
  2214. m_punkScriptingNamespace = saved_m_punkScriptingNamespace;
  2215. m_dwObjectContextCookie = saved_m_dwObjectContextCookie;
  2216. m_pEngineInfo = saved_m_pEngineInfo;
  2217. SetTypeLibWrapper(saved_m_pdispTypeLibWrapper);
  2218. m_pResponse->SwapTemplate(saved_pTemplate);
  2219. m_pResponse->SwapScriptEngineInfo(saved_pvEngineInfo);
  2220. m_szCurrTemplateVirtPath = saved_m_szCurrTemplateVirtPath;
  2221. m_szCurrTemplatePhysPath = saved_m_szCurrTemplatePhysPath;
  2222. // Cleanup
  2223. if (pTemplate)
  2224. pTemplate->Release();
  2225. if (m_pResponse->FResponseAborted() || fTransfer || FHasASPError())
  2226. {
  2227. // propagate Response.End up the script engine chain
  2228. m_pResponse->End();
  2229. }
  2230. // Done
  2231. return hr;
  2232. }
  2233. /*===================================================================
  2234. CHitObj::GetASPError
  2235. Get ASP Error object. Used for Server.GetLastError()
  2236. Parameters
  2237. ppASPError [out] addref'd error object (new or old)
  2238. Returns
  2239. HRESULT
  2240. ===================================================================*/
  2241. HRESULT CHitObj::GetASPError
  2242. (
  2243. IASPError **ppASPError
  2244. )
  2245. {
  2246. Assert(ppASPError);
  2247. if (m_pASPError == NULL)
  2248. {
  2249. // return bogus one
  2250. *ppASPError = new CASPError;
  2251. return (*ppASPError != NULL) ? S_OK : E_OUTOFMEMORY;
  2252. }
  2253. m_pASPError->AddRef(); // return addref'd
  2254. *ppASPError = m_pASPError;
  2255. return S_OK;
  2256. }
  2257. /*===================================================================
  2258. CHitObj::RejectBrowserRequestWhenNeeded
  2259. Request reject-before-execution-started logic
  2260. Parameters:
  2261. dwtQueueWaitTime time request waited in the queue, ms
  2262. pfRejected OUT flag -- TRUE if rejected
  2263. Returns:
  2264. S_OK
  2265. ===================================================================*/
  2266. HRESULT CHitObj::RejectBrowserRequestWhenNeeded
  2267. (
  2268. DWORD dwtQueueWaitTime,
  2269. BOOL *pfRejected
  2270. )
  2271. {
  2272. Assert(FIsBrowserRequest());
  2273. UINT wError = 0;
  2274. // If shutting down
  2275. if (IsShutDownInProgress())
  2276. {
  2277. wError = IDE_SERVER_SHUTTING_DOWN;
  2278. }
  2279. // If waited long enough need to check if still connected
  2280. if (wError == 0)
  2281. {
  2282. DWORD dwConnTestSec = m_pAppln->QueryAppConfig()->dwQueueConnectionTestTime();
  2283. if (dwConnTestSec != 0xffffffff && dwConnTestSec != 0)
  2284. {
  2285. if (dwtQueueWaitTime > (dwConnTestSec * 1000))
  2286. {
  2287. BOOL fConnected = TRUE;
  2288. if (m_pIReq)
  2289. m_pIReq->TestConnection(&fConnected);
  2290. // if client disconnected -- respond with 'Server Error'
  2291. if (!fConnected)
  2292. {
  2293. wError = IDE_500_SERVER_ERROR;
  2294. #ifndef PERF_DISABLE
  2295. g_PerfData.Incr_REQCOMFAILED();
  2296. #endif
  2297. }
  2298. }
  2299. }
  2300. }
  2301. // If waited too long -- reject
  2302. if (wError == 0)
  2303. {
  2304. DWORD dwTimeOutSec = m_pAppln->QueryAppConfig()->dwQueueTimeout();
  2305. if (dwTimeOutSec != 0xffffffff && dwTimeOutSec != 0)
  2306. {
  2307. if (dwtQueueWaitTime > (dwTimeOutSec * 1000))
  2308. {
  2309. wError = IDE_SERVER_TOO_BUSY;
  2310. #ifndef PERF_DISABLE
  2311. g_PerfData.Incr_REQREJECTED();
  2312. #endif
  2313. }
  2314. }
  2315. }
  2316. if (wError)
  2317. {
  2318. m_fExecuting = FALSE; // before 'report error' to disable transfer
  2319. ReportServerError(wError);
  2320. *pfRejected = TRUE;
  2321. }
  2322. else
  2323. {
  2324. *pfRejected = FALSE;
  2325. }
  2326. return S_OK;
  2327. }
  2328. /*===================================================================
  2329. CHitObj::ReportServerError
  2330. Report server error without using the response object
  2331. Parameters:
  2332. ErrorID error message id
  2333. Returns:
  2334. Side effects:
  2335. None.
  2336. ===================================================================*/
  2337. HRESULT CHitObj::ReportServerError
  2338. (
  2339. UINT ErrorId
  2340. )
  2341. {
  2342. // do nothing on non-browser requests or if no WAM_EXEC_INFO
  2343. if (!FIsBrowserRequest() || m_pIReq == NULL)
  2344. return S_OK;
  2345. DWORD dwRequestStatus = HSE_STATUS_ERROR;
  2346. if (ErrorId)
  2347. {
  2348. Handle500Error(ErrorId, m_pIReq);
  2349. }
  2350. m_pIReq->ServerSupportFunction
  2351. (
  2352. HSE_REQ_DONE_WITH_SESSION,
  2353. &dwRequestStatus,
  2354. 0,
  2355. NULL
  2356. );
  2357. SetDoneWithSession();
  2358. return S_OK;
  2359. }
  2360. #ifdef DBG
  2361. /*===================================================================
  2362. CHitObj::AssertValid
  2363. Test to make sure that the CHitObj object is currently correctly formed
  2364. and assert if it is not.
  2365. Returns:
  2366. Side effects:
  2367. None.
  2368. ===================================================================*/
  2369. VOID CHitObj::AssertValid() const
  2370. {
  2371. Assert(m_fInited);
  2372. Assert(FIsValidRequestType());
  2373. if (FIsBrowserRequest())
  2374. {
  2375. Assert(m_pIReq != NULL);
  2376. Assert(m_pPageCompCol != NULL );
  2377. Assert(m_pPageObjMgr != NULL);
  2378. }
  2379. }
  2380. #endif // DBG
  2381. /*===================================================================
  2382. CHitObj::AddObjectContext
  2383. ===================================================================*/
  2384. void CHitObj::AddObjectContext(IASPObjectContext *pASPObjContext)
  2385. {
  2386. HRESULT hr = S_OK;
  2387. Assert(m_dwObjectContextCookie == NULL_GIP_COOKIE);
  2388. Assert(pASPObjContext);
  2389. if (g_pGIT == 0) {
  2390. hr = CoCreateInstance(CLSID_StdGlobalInterfaceTable, 0, CLSCTX_INPROC_SERVER, IID_IGlobalInterfaceTable, (void**) &g_pGIT);
  2391. Assert(hr == S_OK);
  2392. }
  2393. hr = g_pGIT->RegisterInterfaceInGlobal(pASPObjContext, IID_IASPObjectContext, &m_dwObjectContextCookie);
  2394. if (hr != S_OK)
  2395. DBGPRINTF((DBG_CONTEXT, "RegisterInterfaceInGlobal failed, hr = 0x%08X\n", hr));
  2396. Assert(hr == S_OK);
  2397. Assert(m_dwObjectContextCookie != NULL_GIP_COOKIE);
  2398. }
  2399. /*===================================================================
  2400. CHitObj::RemoveObjectContext
  2401. ===================================================================*/
  2402. void CHitObj::RemoveObjectContext()
  2403. {
  2404. HRESULT hr = S_OK;
  2405. if (m_dwObjectContextCookie != NULL_GIP_COOKIE)
  2406. {
  2407. hr = g_pGIT->RevokeInterfaceFromGlobal(m_dwObjectContextCookie);
  2408. if (hr != S_OK)
  2409. DBGPRINTF((DBG_CONTEXT, "RevokeInterfaceFromGlobal failed, hr = 0x%08X\n", hr));
  2410. m_dwObjectContextCookie = NULL_GIP_COOKIE;
  2411. }
  2412. }
  2413. /*===================================================================
  2414. CHitObj::UseObjectContext
  2415. ===================================================================*/
  2416. void CHitObj::UseObjectContext(IASPObjectContext** ppASPObjectContext)
  2417. {
  2418. HRESULT hr = S_OK;
  2419. if (m_dwObjectContextCookie != NULL_GIP_COOKIE)
  2420. {
  2421. hr = g_pGIT->GetInterfaceFromGlobal(m_dwObjectContextCookie, IID_IASPObjectContext, (void**) ppASPObjectContext);
  2422. if (hr != S_OK)
  2423. {
  2424. DBGPRINTF((DBG_CONTEXT, "GetInterfaceFromGlobal failed, hr = 0x%08X\n", hr));
  2425. *ppASPObjectContext = NULL;
  2426. }
  2427. }
  2428. else
  2429. {
  2430. DBG_ASSERT( g_pIASPObjectContextZombie );
  2431. hr = g_pIASPObjectContextZombie->QueryInterface(
  2432. IID_IASPObjectContext,
  2433. reinterpret_cast<void **>(ppASPObjectContext)
  2434. );
  2435. DBG_ASSERT(SUCCEEDED(hr));
  2436. }
  2437. }