Leaked source code of windows server 2003
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

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