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.

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