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.

3068 lines
78 KiB

  1. /*===================================================================
  2. Microsoft Denali
  3. Microsoft Confidential.
  4. Copyright 1996 Microsoft Corporation. All Rights Reserved.
  5. Component: Application Object Manager
  6. File: Applmgr.cpp
  7. Owner: PramodD
  8. This is the Application Manager source file.
  9. ===================================================================*/
  10. #include "denpre.h"
  11. #pragma hdrstop
  12. #include "activdbg.h"
  13. #include "mtacb.h"
  14. #include "debugger.h"
  15. #include "memchk.h"
  16. PTRACE_LOG CAppln::gm_pTraceLog = NULL;
  17. CApplnMgr g_ApplnMgr;
  18. CApplnCleanupMgr g_ApplnCleanupMgr;
  19. DWORD g_nApplications = 0;
  20. DWORD g_nApplicationsRestarting = 0;
  21. DWORD g_nApplicationsRestarted = 0;
  22. LONG g_nAppRestartThreads = 0;
  23. #define DENALI_FILE_NOTIFY_FILTER 0
  24. #pragma warning (disable: 4355) // ignore: "'this' used in base member init
  25. /*===================================================================
  26. S c r i p t E n g i n e C l e a n u p
  27. Node type for linked list of script engines to cleanup
  28. ===================================================================*/
  29. struct CScriptEngineCleanupElem : CDblLink
  30. {
  31. CActiveScriptEngine *m_pEngine;
  32. CScriptEngineCleanupElem(CActiveScriptEngine *pEngine) : m_pEngine(pEngine)
  33. {
  34. m_pEngine->AddRef();
  35. }
  36. ~CScriptEngineCleanupElem()
  37. {
  38. m_pEngine->FinalRelease();
  39. }
  40. };
  41. /*===================================================================
  42. C A p p l n V a r i a n t s
  43. ===================================================================*/
  44. /*===================================================================
  45. CApplnVariants::CApplnVariants
  46. Constructor
  47. Parameters:
  48. Returns:
  49. ===================================================================*/
  50. CApplnVariants::CApplnVariants()
  51. :
  52. m_cRefs(1),
  53. m_pAppln(NULL),
  54. m_ctColType(ctUnknown),
  55. m_ISupportErrImp(this, this, IID_IVariantDictionary)
  56. {
  57. CDispatch::Init(IID_IVariantDictionary);
  58. }
  59. /*===================================================================
  60. CApplnVariants::~CApplnVariants
  61. Constructor
  62. Parameters:
  63. Returns:
  64. ===================================================================*/
  65. CApplnVariants::~CApplnVariants()
  66. {
  67. Assert(!m_pAppln);
  68. }
  69. /*===================================================================
  70. CApplnVariants::Init
  71. Init ApplnVariants
  72. Parameters:
  73. CAppln *pAppln application
  74. CompType ctColType component collection type
  75. Returns:
  76. HRESULT
  77. ===================================================================*/
  78. HRESULT CApplnVariants::Init
  79. (
  80. CAppln *pAppln,
  81. CompType ctColType
  82. )
  83. {
  84. Assert(pAppln);
  85. pAppln->AddRef();
  86. Assert(!m_pAppln);
  87. m_pAppln = pAppln;
  88. m_ctColType = ctColType;
  89. return S_OK;
  90. }
  91. /*===================================================================
  92. CApplnVariants::UnInit
  93. UnInit ApplnVariants
  94. Parameters:
  95. Returns:
  96. HRESULT
  97. ===================================================================*/
  98. HRESULT CApplnVariants::UnInit()
  99. {
  100. if (m_pAppln)
  101. {
  102. m_pAppln->Release();
  103. m_pAppln = NULL;
  104. }
  105. return S_OK;
  106. }
  107. /*===================================================================
  108. CApplnVariants::QueryInterface
  109. CApplnVariants::AddRef
  110. CApplnVariants::Release
  111. IUnknown members for CApplnVariants object.
  112. ===================================================================*/
  113. STDMETHODIMP CApplnVariants::QueryInterface
  114. (
  115. REFIID iid,
  116. void **ppvObj
  117. )
  118. {
  119. if (iid == IID_IUnknown || iid == IID_IDispatch ||
  120. iid == IID_IVariantDictionary)
  121. {
  122. AddRef();
  123. *ppvObj = this;
  124. return S_OK;
  125. }
  126. else if (iid == IID_ISupportErrorInfo)
  127. {
  128. m_ISupportErrImp.AddRef();
  129. *ppvObj = &m_ISupportErrImp;
  130. return S_OK;
  131. }
  132. *ppvObj = NULL;
  133. return E_NOINTERFACE;
  134. }
  135. STDMETHODIMP_(ULONG) CApplnVariants::AddRef()
  136. {
  137. return InterlockedIncrement((LPLONG)&m_cRefs);
  138. }
  139. STDMETHODIMP_(ULONG) CApplnVariants::Release()
  140. {
  141. if (InterlockedDecrement((LPLONG)&m_cRefs) > 0)
  142. return m_cRefs;
  143. delete this;
  144. return 0;
  145. }
  146. /*===================================================================
  147. CApplnVariants::ObjectNameFromVariant
  148. Gets name from variant. Resolves operations by index.
  149. Allocates memory for name.
  150. Parameters:
  151. vKey VARIANT
  152. ppwszName [out] allocated name
  153. fVerify flag - check existance if named
  154. Returns:
  155. HRESULT
  156. ===================================================================*/
  157. HRESULT CApplnVariants::ObjectNameFromVariant
  158. (
  159. VARIANT &vKey,
  160. WCHAR **ppwszName,
  161. BOOL fVerify
  162. )
  163. {
  164. *ppwszName = NULL;
  165. if (!m_pAppln->PCompCol())
  166. return E_FAIL;
  167. VARIANT *pvarKey = &vKey;
  168. VARIANT varKeyCopy;
  169. VariantInit(&varKeyCopy);
  170. if (V_VT(pvarKey) != VT_BSTR && V_VT(pvarKey) != VT_I2 && V_VT(pvarKey) != VT_I4)
  171. {
  172. if (FAILED(VariantResolveDispatch(&varKeyCopy, &vKey, IID_IVariantDictionary, IDE_APPLICATION)))
  173. {
  174. ExceptionId(IID_IVariantDictionary, IDE_APPLICATION, IDE_EXPECTING_STR);
  175. VariantClear(&varKeyCopy);
  176. return E_FAIL;
  177. }
  178. pvarKey = &varKeyCopy;
  179. }
  180. LPWSTR pwszName = NULL;
  181. switch (V_VT(pvarKey))
  182. {
  183. case VT_BSTR:
  184. {
  185. pwszName = V_BSTR(pvarKey);
  186. if (fVerify && pwszName)
  187. {
  188. CComponentObject *pObj = NULL;
  189. Assert(m_pAppln);
  190. Assert(m_pAppln->PCompCol());
  191. if (m_ctColType == ctTagged)
  192. m_pAppln->PCompCol()->GetTagged(pwszName, &pObj);
  193. else
  194. m_pAppln->PCompCol()->GetProperty(pwszName, &pObj);
  195. if (!pObj || pObj->GetType() != m_ctColType)
  196. pwszName = NULL; // as if not found
  197. }
  198. break;
  199. }
  200. case VT_I1: case VT_I2: case VT_I8:
  201. case VT_UI1: case VT_UI2: case VT_UI4: case VT_UI8:
  202. case VT_R4: case VT_R8:
  203. // Coerce all integral types to VT_I4
  204. if (FAILED(VariantChangeType(pvarKey, pvarKey, 0, VT_I4)))
  205. return E_FAIL;
  206. // fallthru to VT_I4
  207. case VT_I4:
  208. {
  209. int i;
  210. // Look up the object by index
  211. i = V_I4(pvarKey);
  212. if (i > 0)
  213. {
  214. Assert(m_pAppln);
  215. Assert(m_pAppln->PCompCol());
  216. m_pAppln->PCompCol()->GetNameByIndex
  217. (
  218. m_ctColType,
  219. i,
  220. &pwszName
  221. );
  222. }
  223. break;
  224. }
  225. }
  226. if (pwszName)
  227. {
  228. *ppwszName = StringDupW(pwszName);
  229. }
  230. VariantClear(&varKeyCopy);
  231. return S_OK;
  232. }
  233. /*===================================================================
  234. CApplnVariants::get_Item
  235. Function called from DispInvoke to get keys from the collection.
  236. Parameters:
  237. vKey VARIANT [in], which parameter to get the value of - integers access collection as an array
  238. pvarReturn VARIANT *, [out] value of the requested parameter
  239. Returns:
  240. S_OK on success, E_FAIL on failure.
  241. ===================================================================*/
  242. HRESULT CApplnVariants::get_Item
  243. (
  244. VARIANT varKey,
  245. VARIANT *pVar
  246. )
  247. {
  248. if (!m_pAppln || FAILED(m_pAppln->CheckForTombstone()))
  249. return E_FAIL;
  250. // Initialize return value
  251. VariantInit(pVar);
  252. if (!m_pAppln->PCompCol())
  253. return S_OK;
  254. // Get HitObj from Viper if Tagged Variants
  255. CHitObj *pHitObj = NULL;
  256. if (m_ctColType == ctTagged)
  257. {
  258. ViperGetHitObjFromContext(&pHitObj);
  259. if (!pHitObj)
  260. return S_OK; // return emtpy variant
  261. }
  262. m_pAppln->Lock();
  263. // Get name
  264. WCHAR *pwszName = NULL;
  265. HRESULT hr = ObjectNameFromVariant(varKey, &pwszName);
  266. if (!pwszName)
  267. {
  268. m_pAppln->UnLock();
  269. return hr;
  270. }
  271. // Find object by name
  272. CComponentObject *pObj = NULL;
  273. if (m_ctColType == ctTagged)
  274. {
  275. Assert(pHitObj);
  276. // need to go through HitObj for instantiation
  277. pHitObj->GetComponent(csAppln, pwszName, CbWStr(pwszName), &pObj);
  278. if (pObj && (pObj->GetType() != ctTagged))
  279. pObj = NULL;
  280. }
  281. else
  282. {
  283. m_pAppln->PCompCol()->GetProperty(pwszName, &pObj);
  284. }
  285. if (pObj)
  286. pObj->GetVariant(pVar);
  287. m_pAppln->UnLock();
  288. free(pwszName);
  289. return S_OK;
  290. }
  291. /*===================================================================
  292. CApplnVariants::put_Item
  293. OLE automation put for Item property
  294. Parameters:
  295. varKey key
  296. Var value
  297. Returns:
  298. S_OK on success, E_FAIL on failure.
  299. ===================================================================*/
  300. HRESULT CApplnVariants::put_Item
  301. (
  302. VARIANT varKey,
  303. VARIANT Var
  304. )
  305. {
  306. if (!m_pAppln || FAILED(m_pAppln->CheckForTombstone()))
  307. return E_FAIL;
  308. if (m_ctColType == ctTagged)
  309. {
  310. ExceptionId(IID_IVariantDictionary, IDE_APPLICATION,
  311. IDE_CANT_MOD_STATICOBJECTS);
  312. return E_FAIL;
  313. }
  314. Assert(m_ctColType == ctProperty);
  315. if (!m_pAppln->PCompCol())
  316. return E_FAIL;
  317. m_pAppln->Lock();
  318. // Resolve the variant
  319. VARIANT varResolved;
  320. HRESULT hr = VariantResolveDispatch
  321. (
  322. &varResolved,
  323. &Var,
  324. IID_IApplicationObject,
  325. IDE_APPLICATION
  326. );
  327. if (FAILED(hr))
  328. {
  329. m_pAppln->UnLock();
  330. return hr; // exception already raised
  331. }
  332. // Get name
  333. WCHAR *pwszName = NULL;
  334. hr = ObjectNameFromVariant(varKey, &pwszName);
  335. if (pwszName)
  336. {
  337. // Set the property
  338. if (m_pAppln->PCompCol())
  339. hr = m_pAppln->PCompCol()->AddProperty(pwszName, &varResolved);
  340. else
  341. hr = E_FAIL; // not likely if application not UnInited
  342. }
  343. VariantClear(&varResolved);
  344. m_pAppln->UnLock();
  345. if (hr == RPC_E_WRONG_THREAD)
  346. {
  347. // We use RPC_E_WRONG_THREAD to indicate bad model object
  348. ExceptionId(IID_IApplicationObject,
  349. IDE_APPLICATION, IDE_APPLICATION_CANT_STORE_OBJECT);
  350. hr = E_FAIL;
  351. }
  352. free(pwszName);
  353. return hr;
  354. }
  355. /*===================================================================
  356. CApplnVariants::putref_Item
  357. OLE automation putref for Item property
  358. Parameters:
  359. varKey key
  360. Var value
  361. Returns:
  362. S_OK on success, E_FAIL on failure.
  363. ===================================================================*/
  364. HRESULT CApplnVariants::putref_Item
  365. (
  366. VARIANT varKey,
  367. VARIANT Var
  368. )
  369. {
  370. if (!m_pAppln || FAILED(m_pAppln->CheckForTombstone()))
  371. return E_FAIL;
  372. if (m_ctColType == ctTagged)
  373. {
  374. ExceptionId(IID_IVariantDictionary, IDE_APPLICATION,
  375. IDE_CANT_MOD_STATICOBJECTS);
  376. return E_FAIL;
  377. }
  378. if (FIsIntrinsic(&Var))
  379. {
  380. ExceptionId(IID_IVariantDictionary, IDE_APPLICATION, IDE_APPLICATION_CANT_STORE_INTRINSIC);
  381. return E_FAIL;
  382. }
  383. Assert(m_ctColType == ctProperty);
  384. if (!m_pAppln->PCompCol())
  385. return E_FAIL;
  386. m_pAppln->Lock();
  387. // Get name
  388. WCHAR *pwszName = NULL;
  389. HRESULT hr = ObjectNameFromVariant(varKey, &pwszName);
  390. if (pwszName)
  391. {
  392. // Set the property
  393. if (m_pAppln->PCompCol())
  394. hr = m_pAppln->PCompCol()->AddProperty(pwszName, &Var);
  395. else
  396. hr = E_FAIL; // not likely if application not UnInited
  397. }
  398. m_pAppln->UnLock();
  399. if (hr == RPC_E_WRONG_THREAD)
  400. {
  401. // We use RPC_E_WRONG_THREAD to indicate bad model object
  402. ExceptionId(IID_IApplicationObject,
  403. IDE_APPLICATION, IDE_APPLICATION_CANT_STORE_OBJECT);
  404. hr = E_FAIL;
  405. }
  406. if (pwszName)
  407. free(pwszName);
  408. return hr;
  409. }
  410. /*===================================================================
  411. CApplnVariants::get_Key
  412. Function called from DispInvoke to get values from the collection.
  413. Parameters:
  414. vKey VARIANT [in], which parameter to get the value of - integers access collection as an array
  415. pvarReturn VARIANT *, [out] value of the requested parameter
  416. Returns:
  417. S_OK on success, E_FAIL on failure.
  418. ===================================================================*/
  419. HRESULT CApplnVariants::get_Key
  420. (
  421. VARIANT varKey,
  422. VARIANT *pVar
  423. )
  424. {
  425. if (!m_pAppln || FAILED(m_pAppln->CheckForTombstone()))
  426. return E_FAIL;
  427. VariantInit(pVar);
  428. if (!m_pAppln->PCompCol())
  429. return S_OK;
  430. m_pAppln->Lock();
  431. // Get name
  432. WCHAR *pwszName = NULL;
  433. HRESULT hr = ObjectNameFromVariant(varKey, &pwszName, TRUE);
  434. m_pAppln->UnLock();
  435. if (!pwszName)
  436. return hr;
  437. // Return BSTr
  438. BSTR bstrT = SysAllocString(pwszName);
  439. free(pwszName);
  440. if (!bstrT)
  441. return E_OUTOFMEMORY;
  442. V_VT(pVar) = VT_BSTR;
  443. V_BSTR(pVar) = bstrT;
  444. return S_OK;
  445. }
  446. /*===================================================================
  447. CApplnVariants::get_Count
  448. Parameters:
  449. pcValues - count is stored in *pcValues
  450. ===================================================================*/
  451. STDMETHODIMP CApplnVariants::get_Count
  452. (
  453. int *pcValues
  454. )
  455. {
  456. if (!m_pAppln || FAILED(m_pAppln->CheckForTombstone()))
  457. return E_FAIL;
  458. if (m_ctColType == ctTagged)
  459. *pcValues = m_pAppln->m_pApplCompCol->GetTaggedObjectCount();
  460. else
  461. *pcValues = m_pAppln->m_pApplCompCol->GetPropertyCount();
  462. return S_OK;
  463. }
  464. /*===================================================================
  465. CApplnVariants::get__NewEnum
  466. Return a new enumerator
  467. ===================================================================*/
  468. HRESULT CApplnVariants::get__NewEnum
  469. (
  470. IUnknown **ppEnumReturn
  471. )
  472. {
  473. if (!m_pAppln || FAILED(m_pAppln->CheckForTombstone()))
  474. return E_FAIL;
  475. *ppEnumReturn = NULL;
  476. CVariantsIterator *pIterator = new CVariantsIterator(m_pAppln, m_ctColType);
  477. if (pIterator == NULL)
  478. {
  479. ExceptionId(IID_IVariantDictionary, IDE_SESSION, IDE_OOM);
  480. return E_OUTOFMEMORY;
  481. }
  482. *ppEnumReturn = pIterator;
  483. return S_OK;
  484. }
  485. /*===================================================================
  486. CApplnVariants::Remove
  487. Remove item
  488. Parameters:
  489. varKey key
  490. Returns:
  491. S_OK on success, E_FAIL on failure.
  492. ===================================================================*/
  493. HRESULT CApplnVariants::Remove
  494. (
  495. VARIANT varKey
  496. )
  497. {
  498. if (!m_pAppln || FAILED(m_pAppln->CheckForTombstone()))
  499. return E_FAIL;
  500. if (m_ctColType == ctTagged)
  501. {
  502. ExceptionId(IID_IVariantDictionary, IDE_APPLICATION,
  503. IDE_CANT_MOD_STATICOBJECTS);
  504. return E_FAIL;
  505. }
  506. Assert(m_ctColType == ctProperty);
  507. m_pAppln->Lock();
  508. // Get name
  509. WCHAR *pwszName = NULL;
  510. ObjectNameFromVariant(varKey, &pwszName);
  511. if (pwszName)
  512. {
  513. CComponentCollection *pCompCol = m_pAppln->PCompCol();
  514. // Set the property
  515. if (pCompCol)
  516. pCompCol->RemoveProperty(pwszName);
  517. free(pwszName);
  518. }
  519. m_pAppln->UnLock();
  520. return S_OK;
  521. }
  522. /*===================================================================
  523. CApplnVariants::RemoveAll
  524. Remove all items
  525. Parameters:
  526. varKey key
  527. Returns:
  528. S_OK on success, E_FAIL on failure.
  529. ===================================================================*/
  530. HRESULT CApplnVariants::RemoveAll()
  531. {
  532. if (!m_pAppln || FAILED(m_pAppln->CheckForTombstone()))
  533. return E_FAIL;
  534. if (m_ctColType == ctTagged)
  535. {
  536. ExceptionId(IID_IVariantDictionary, IDE_APPLICATION,
  537. IDE_CANT_MOD_STATICOBJECTS);
  538. return E_FAIL;
  539. }
  540. Assert(m_ctColType == ctProperty);
  541. m_pAppln->Lock();
  542. CComponentCollection *pCompCol = m_pAppln->PCompCol();
  543. if (pCompCol)
  544. {
  545. pCompCol->RemoveAllProperties();
  546. }
  547. m_pAppln->UnLock();
  548. return S_OK;
  549. }
  550. /*===================================================================
  551. C A p p l n
  552. ===================================================================*/
  553. /*===================================================================
  554. CAppln::CAppln
  555. Constructor
  556. Parameters:
  557. NONE
  558. Returns:
  559. NONE
  560. ===================================================================*/
  561. CAppln::CAppln()
  562. :
  563. m_fInited(FALSE),
  564. m_fFirstRequestRan(FALSE),
  565. m_fGlobalChanged(FALSE),
  566. m_fDeleteInProgress(FALSE),
  567. m_fTombstone(FALSE),
  568. m_fDebuggable(FALSE),
  569. m_fNotificationAdded(FALSE),
  570. m_fUseImpersonationHandle(FALSE),
  571. m_cRefs(1),
  572. m_pszMetabaseKey(NULL),
  573. m_pszApplnPath(NULL),
  574. m_pszGlobalAsa(NULL),
  575. m_pGlobalTemplate(NULL),
  576. m_cSessions(0),
  577. m_cRequests(0),
  578. m_pSessionMgr(NULL),
  579. m_pApplCompCol(NULL),
  580. m_pProperties(NULL),
  581. m_pTaggedObjects(NULL),
  582. m_pAppRoot(NULL),
  583. m_pActivity(NULL),
  584. m_dwLockThreadID(INVALID_THREADID),
  585. m_cLockRefCount(0),
  586. m_hUserImpersonation(NULL),
  587. m_pdispGlobTypeLibWrapper(NULL),
  588. m_pServicesConfig(NULL)
  589. {
  590. // COM stuff
  591. m_ISuppErrImp.Init(static_cast<IApplicationObject *>(this),
  592. static_cast<IApplicationObject *>(this),
  593. IID_IApplicationObject);
  594. CDispatch::Init(IID_IApplicationObject);
  595. IF_DEBUG(APPLICATION) {
  596. WriteRefTraceLog(gm_pTraceLog, m_cRefs, this);
  597. }
  598. }
  599. /*===================================================================
  600. CAppln::~CAppln
  601. Destructor
  602. Parameters:
  603. NONE
  604. Returns:
  605. NONE
  606. ===================================================================*/
  607. CAppln::~CAppln()
  608. {
  609. Assert(m_fTombstone); // must be tombstoned before destructor
  610. Assert(m_cRefs == 0); // must have 0 ref count
  611. #ifdef DBG_NOTIFICATION
  612. DBGPRINTF((DBG_CONTEXT, "Deleting application %p\n", this));
  613. #endif // DBG_NOTIFICATION
  614. }
  615. /*===================================================================
  616. HRESULT CAppln::Init
  617. Initialize object
  618. Parameters:
  619. char *pszApplnKey application's metabase key
  620. char *pszApplnPath application's directory path
  621. CIsapiReqInfo *pIReq Isapi Req Info
  622. HANDLE hUserImpersonation impersonation handle
  623. Returns:
  624. S_OK Success
  625. E_FAIL Failure
  626. E_OUTOFMEMORY Out of memory failure
  627. ===================================================================*/
  628. HRESULT CAppln::Init
  629. (
  630. TCHAR *pszApplnKey,
  631. TCHAR *pszApplnPath,
  632. CIsapiReqInfo *pIReq,
  633. HANDLE hUserImpersonation
  634. )
  635. {
  636. HRESULT hr = S_OK;
  637. CMBCSToWChar convStr;
  638. InterlockedIncrement((LPLONG)&g_nApplications);
  639. Assert(pszApplnKey);
  640. Assert(pszApplnPath);
  641. void *pHashKey = NULL;
  642. DWORD dwHashKeyLength = 0;
  643. DWORD cch;
  644. // Debugging variables (These are placed here for possible cleanup)
  645. IDebugApplicationNode *pVirtualServerRoot = NULL;
  646. CFileNode *pFileNode = NULL;
  647. // Critical sections created together --
  648. // they are deleted in the destructor based on m_fInited flag
  649. ErrInitCriticalSection(&m_csInternalLock, hr);
  650. if (SUCCEEDED(hr))
  651. {
  652. ErrInitCriticalSection(&m_csApplnLock, hr);
  653. if (FAILED(hr))
  654. DeleteCriticalSection(&m_csInternalLock);
  655. }
  656. if (FAILED(hr))
  657. {
  658. DBGPRINTF((DBG_CONTEXT, "New Application Failed to acquire Critical Section, hr = %08x\n", hr));
  659. return hr;
  660. }
  661. // Remember (copy of) metabase key
  662. cch = _tcslen(pszApplnKey);
  663. m_pszMetabaseKey = new TCHAR[(cch+1) * sizeof(TCHAR)];
  664. if (!m_pszMetabaseKey)
  665. goto LCleanupOOM;
  666. memcpy(m_pszMetabaseKey, pszApplnKey, (cch+1)*sizeof(TCHAR));
  667. pHashKey = m_pszMetabaseKey;
  668. dwHashKeyLength = cch * sizeof(TCHAR);
  669. // Remember (copy of) appln path
  670. cch = _tcslen(pszApplnPath);
  671. m_pszApplnPath = new TCHAR[(cch+1) * sizeof(TCHAR)];
  672. if (!m_pszApplnPath)
  673. goto LCleanupOOM;
  674. memcpy(m_pszApplnPath, pszApplnPath, (cch+1)*sizeof(TCHAR));
  675. // Get virtual path of appln & remember what it is
  676. TCHAR szApplnVRoot[256];
  677. if (FAILED(FindApplicationPath(pIReq, szApplnVRoot, sizeof szApplnVRoot)))
  678. {
  679. DBGWARN((DBG_CONTEXT, "New Application Failed to FindApplicationPath(), hr = %#08x\n", hr));
  680. goto LCleanup;
  681. }
  682. if ((m_pszApplnVRoot = new TCHAR [(_tcslen(szApplnVRoot) + 1)*sizeof(TCHAR)]) == NULL)
  683. goto LCleanupOOM;
  684. _tcscpy(m_pszApplnVRoot, szApplnVRoot);
  685. // Initialize link element with key
  686. Assert(pHashKey);
  687. Assert(dwHashKeyLength);
  688. if (FAILED(CLinkElem::Init(pHashKey, dwHashKeyLength)))
  689. goto LCleanupOOM;
  690. // Setup impersonation
  691. m_fNotificationAdded = FALSE;
  692. if (FIsWinNT() && pszApplnPath &&
  693. pszApplnPath[0] ==_T('\\') && pszApplnPath[1] == _T('\\'))
  694. {
  695. m_fUseImpersonationHandle = DuplicateToken
  696. (
  697. hUserImpersonation,
  698. SecurityImpersonation,
  699. &m_hUserImpersonation
  700. );
  701. }
  702. m_cSessions = 0;
  703. m_cRequests = 0;
  704. // Create and init app config
  705. m_pAppConfig = new CAppConfig();
  706. if (!m_pAppConfig)
  707. goto LCleanupOOM;
  708. hr = m_pAppConfig->Init(pIReq, this);
  709. if (FAILED(hr))
  710. {
  711. DBGWARN((DBG_CONTEXT, "New Application Failed: Could not Init the AppConfig, hr = %#08x\n", hr));
  712. goto LCleanup;
  713. }
  714. // Create and init application level component collection
  715. m_pApplCompCol = new CComponentCollection;
  716. if (!m_pApplCompCol)
  717. goto LCleanupOOM;
  718. hr = m_pApplCompCol->Init(csAppln);
  719. if (FAILED(hr))
  720. {
  721. DBGWARN((DBG_CONTEXT, "New Application Failed: Could not Init the Component Collection, hr = %#08x\n", hr));
  722. goto LCleanup;
  723. }
  724. // initialize application properties collection
  725. m_pProperties = new CApplnVariants;
  726. if (!m_pProperties)
  727. goto LCleanupOOM;
  728. hr = m_pProperties->Init(this, ctProperty);
  729. if (FAILED(hr))
  730. {
  731. DBGWARN((DBG_CONTEXT, "New Application Failed: Could not Init the Application Properties, hr = %#08x\n", hr));
  732. goto LCleanup;
  733. }
  734. // initialize application tagged object collection
  735. m_pTaggedObjects = new CApplnVariants;
  736. if (!m_pTaggedObjects)
  737. goto LCleanupOOM;
  738. hr = m_pTaggedObjects->Init(this, ctTagged);
  739. if (FAILED(hr))
  740. {
  741. DBGWARN((DBG_CONTEXT, "New Application Failed: Could not Init the Application Tagged Objects, hr = %#08x\n", hr));
  742. goto LCleanup;
  743. }
  744. // Initialize the CServicesConfig Object
  745. hr = InitServicesConfig();
  746. if (FAILED(hr)) {
  747. DBGWARN((DBG_CONTEXT, "New Application Failed: Could not Init ServicesConfig, hr = %#08x\n", hr));
  748. goto LCleanup;
  749. }
  750. // Debugging support - Create an application node
  751. // If PDM does not exist it means debugger not installed or it's Win 95
  752. //
  753. if (g_pPDM)
  754. {
  755. // Debugging directories are shown as:
  756. //
  757. // <virtual web server>
  758. // <application name>
  759. // <path to ASP>
  760. //
  761. // Get a pointer to the document node containing the virtual web server.
  762. if (FAILED(hr = GetServerDebugRoot(pIReq, &pVirtualServerRoot)))
  763. {
  764. DBGWARN((DBG_CONTEXT, "New Application Failed: Could not GetServerDebugRoot(), hr = %#08x\n", hr));
  765. goto LCleanup;
  766. }
  767. // Create a node for this application
  768. if (FAILED(hr = g_pDebugApp->CreateApplicationNode(&m_pAppRoot)))
  769. {
  770. DBGWARN((DBG_CONTEXT, "New Application Failed: Could not CreateApplicationNode(), hr = %#08x\n", hr));
  771. goto LCleanup;
  772. }
  773. // Create a doc provider for the node
  774. if ((pFileNode = new CFileNode) == NULL)
  775. goto LCleanupOOM;
  776. // Name the application
  777. TCHAR szDebugApp[256];
  778. TCHAR *pchEnd = strcpyEx(szDebugApp, m_pszApplnVRoot);
  779. if (! QueryAppConfig()->fAllowDebugging()) {
  780. #if UNICODE
  781. CwchLoadStringOfId(
  782. #else
  783. CchLoadStringOfId(
  784. #endif
  785. IDS_DEBUGGING_DISABLED, pchEnd, DIFF(&szDebugApp[sizeof (szDebugApp)/sizeof(TCHAR)] - pchEnd));
  786. m_fDebuggable = FALSE;
  787. }
  788. else
  789. m_fDebuggable = TRUE;
  790. Assert (_tcslen(szDebugApp) < (sizeof(szDebugApp)/sizeof(TCHAR)));
  791. WCHAR *pswzDebugApp;
  792. #if UNICODE
  793. pswzDebugApp = szDebugApp;
  794. #else
  795. if (FAILED(hr = convStr.Init(szDebugApp))) {
  796. DBGWARN((DBG_CONTEXT, "New Application Failed: Cannot convert szDebugApp to UNICODE, hr = %#08x\n", hr));
  797. goto LCleanup;
  798. }
  799. pswzDebugApp = convStr.GetString();
  800. #endif
  801. if (FAILED(hr = pFileNode->Init(pswzDebugApp)))
  802. {
  803. DBGWARN((DBG_CONTEXT, "New Application Failed: Cannot Init CFileNode, hr = %#08x\n", hr));
  804. goto LCleanup;
  805. }
  806. if (FAILED(hr = m_pAppRoot->SetDocumentProvider(pFileNode)))
  807. {
  808. DBGWARN((DBG_CONTEXT, "New Application Failed: SetDocumentProvider failed, hr = %#08x\n", hr));
  809. goto LCleanup;
  810. }
  811. // Attach to the UI
  812. if (FAILED(hr = m_pAppRoot->Attach(pVirtualServerRoot)))
  813. {
  814. DBGWARN((DBG_CONTEXT, "New Application Failed: Could not Attach to debugger, hr = %#08x\n", hr));
  815. goto LCleanup;
  816. }
  817. // If this application had a previous incarnation (changed global.asa
  818. // or debugging being flipped on in midstream), then there may be some
  819. // documents in the cache which should be added to the debugger now.
  820. if (m_fDebuggable)
  821. {
  822. g_TemplateCache.AddApplicationToDebuggerUI(this);
  823. // create the global debug activity if it hasn't been created already
  824. if (g_pDebugActivity == NULL) {
  825. g_pDebugActivity = new CViperActivity;
  826. if (g_pDebugActivity == NULL) {
  827. hr = E_OUTOFMEMORY;
  828. goto LCleanup;
  829. }
  830. if (FAILED(hr = g_pDebugActivity->Init(m_pServicesConfig))) {
  831. DBGWARN((DBG_CONTEXT, "New Application Failed: Could not create global debug activity, hr = %#08x\n", hr));
  832. goto LCleanup;
  833. }
  834. }
  835. // In DEBUG mode: all requests run on the same thread
  836. if (FAILED(hr = BindToActivity(g_pDebugActivity)))
  837. {
  838. DBGWARN((DBG_CONTEXT, "New Application Failed: Could not bind application to debugging activity, hr = %#08x\n", hr));
  839. goto LCleanup;
  840. }
  841. }
  842. }
  843. // For Win95: all requests run on the same thread
  844. if (!FIsWinNT())
  845. {
  846. if (FAILED(hr = BindToActivity()))
  847. {
  848. DBGWARN((DBG_CONTEXT, "New Application Failed: Could not bind application to Win95 activity, hr = %#08x\n", hr));
  849. goto LCleanup;
  850. }
  851. }
  852. // Create and init session manager
  853. m_pSessionMgr = new CSessionMgr;
  854. if (!m_pSessionMgr)
  855. goto LCleanupOOM;
  856. hr = m_pSessionMgr->Init(this);
  857. if (FAILED(hr)) {
  858. DBGWARN((DBG_CONTEXT, "New Application Failed: Could not Init session manager, hr = %#08x\n", hr));
  859. goto LCleanup;
  860. }
  861. LCleanup:
  862. // Release interfaces
  863. if (pFileNode)
  864. pFileNode->Release();
  865. if (pVirtualServerRoot)
  866. pVirtualServerRoot->Release();
  867. if (SUCCEEDED(hr))
  868. m_fInited = TRUE;
  869. return hr;
  870. LCleanupOOM:
  871. hr = E_OUTOFMEMORY;
  872. DBGERROR((DBG_CONTEXT, "New Application Failed: E_OUTOFMEMORY\n"));
  873. goto LCleanup;
  874. }
  875. /*===================================================================
  876. CAppln::InitServicesConfig
  877. Initializes the Application scoped CServicesConfig object
  878. ===================================================================*/
  879. HRESULT CAppln::InitServicesConfig()
  880. {
  881. HRESULT hr;
  882. IServiceThreadPoolConfig *pIThreadPool = NULL;
  883. IServiceSynchronizationConfig *pISyncConfig = NULL;
  884. IServicePartitionConfig *pIPartitionConfig = NULL;
  885. IServiceSxsConfig *pISxsConfig = NULL;
  886. hr = CoCreateInstance(CLSID_CServiceConfig,
  887. NULL,
  888. CLSCTX_INPROC_SERVER,
  889. IID_IUnknown,
  890. (void **)&m_pServicesConfig);
  891. if (FAILED(hr)) {
  892. DBGWARN((DBG_CONTEXT, "New Application Failed: InitServicesConfig() - Could not CCI ServicesConfig, hr = %#08x\n", hr));
  893. goto LCleanup;
  894. }
  895. hr = m_pServicesConfig->QueryInterface(IID_IServiceThreadPoolConfig, (void **)&pIThreadPool);
  896. if (FAILED(hr)) {
  897. DBGWARN((DBG_CONTEXT, "New Application Failed: InitServicesConfig() - Could not QI for IServiceThreadPoolConfig, hr = %#08x\n", hr));
  898. goto LCleanup;
  899. }
  900. hr = pIThreadPool->SelectThreadPool(m_pAppConfig->fExecuteInMTA() ? CSC_MTAThreadPool : CSC_STAThreadPool);
  901. if (FAILED(hr)) {
  902. DBGWARN((DBG_CONTEXT, "New Application Failed: InitServicesConfig() - Failed to SelectThreadPool, hr = %#08x\n", hr));
  903. goto LCleanup;
  904. }
  905. hr = m_pServicesConfig->QueryInterface(IID_IServiceSynchronizationConfig, (void **)&pISyncConfig);
  906. if (FAILED(hr)) {
  907. DBGWARN((DBG_CONTEXT, "New Application Failed: InitServicesConfig() - Could not QI for IServiceSynchronizationConfig, hr = %#08x\n", hr));
  908. goto LCleanup;
  909. }
  910. hr = pISyncConfig->ConfigureSynchronization (CSC_IfContainerIsSynchronized);
  911. if (FAILED(hr)) {
  912. DBGWARN((DBG_CONTEXT, "New Application Failed: InitServicesConfig() - Could not ConfigureSynchronization, hr = %#08x\n", hr));
  913. goto LCleanup;
  914. }
  915. if (m_pAppConfig->fUsePartition() && m_pAppConfig->PPartitionGUID()) {
  916. hr = m_pServicesConfig->QueryInterface(IID_IServicePartitionConfig, (void **)&pIPartitionConfig);
  917. if (FAILED(hr)) {
  918. DBGWARN((DBG_CONTEXT, "New Application Failed: InitServicesConfig() - Could not QI for IServicePartitionConfig, hr = %#08x\n", hr));
  919. goto LCleanup;
  920. }
  921. hr = pIPartitionConfig->PartitionConfig(CSC_NewPartition);
  922. if (FAILED(hr)) {
  923. DBGWARN((DBG_CONTEXT, "New Application Failed: InitServicesConfig() - Could not set PartitionConfig, hr = %#08x\n", hr));
  924. goto LCleanup;
  925. }
  926. hr = pIPartitionConfig->PartitionID(*m_pAppConfig->PPartitionGUID());
  927. if (FAILED(hr)) {
  928. DBGWARN((DBG_CONTEXT, "New Application Failed: InitServicesConfig() - Could not set PartitionID, hr = %#08x\n", hr));
  929. goto LCleanup;
  930. }
  931. }
  932. if (m_pAppConfig->fSxsEnabled()) {
  933. hr = m_pServicesConfig->QueryInterface(IID_IServiceSxsConfig, (void **)&pISxsConfig);
  934. if (FAILED(hr)) {
  935. DBGWARN((DBG_CONTEXT, "New Application Failed: InitServicesConfig() - Could not QI for IServiceSxsConfig, hr = %#08x\n", hr));
  936. goto LCleanup;
  937. }
  938. hr = pISxsConfig->SxsConfig(CSC_NewSxs);
  939. if (FAILED(hr)) {
  940. DBGWARN((DBG_CONTEXT, "New Application Failed: InitServicesConfig() - Could not set SxsConfig, hr = %#08x\n", hr));
  941. goto LCleanup;
  942. }
  943. LPWSTR pwszApplnPath;
  944. #if UNICODE
  945. pwszApplnPath = m_pszApplnPath;
  946. #else
  947. CMBCSToWChar convPath;
  948. hr = convPath.Init(m_pszApplnPath);
  949. if (FAILED(hr)) {
  950. DBGWARN((DBG_CONTEXT, "New Application Failed: InitServicesConfig() - Could not convert ApplnPath to UNICODE, hr = %#08x\n", hr));
  951. goto LCleanup;
  952. }
  953. pwszApplnPath = convPath.GetString();
  954. #endif
  955. hr = pISxsConfig->SxsDirectory(pwszApplnPath);
  956. if (FAILED(hr)) {
  957. DBGWARN((DBG_CONTEXT, "New Application Failed: InitServicesConfig() - Could not set SxsDirectory, hr = %#08x\n", hr));
  958. goto LCleanup;
  959. }
  960. if (m_pAppConfig->szSxsName() && *m_pAppConfig->szSxsName()) {
  961. CMBCSToWChar convName;
  962. hr = convName.Init(m_pAppConfig->szSxsName());
  963. if (FAILED(hr)) {
  964. DBGWARN((DBG_CONTEXT, "New Application Failed: InitServicesConfig() - Could not convert SxsName to UNICODE, hr = %#08x\n", hr));
  965. goto LCleanup;
  966. }
  967. hr = pISxsConfig->SxsName(convName.GetString());
  968. if (FAILED(hr)) {
  969. DBGWARN((DBG_CONTEXT, "New Application Failed: InitServicesConfig() - Could not set SxsName, hr = %#08x\n", hr));
  970. goto LCleanup;
  971. }
  972. }
  973. }
  974. LCleanup:
  975. if (pIThreadPool)
  976. pIThreadPool->Release();
  977. if (pISyncConfig)
  978. pISyncConfig->Release();
  979. if (pIPartitionConfig)
  980. pIPartitionConfig->Release();
  981. if (pISxsConfig)
  982. pISxsConfig->Release();
  983. return hr;
  984. }
  985. /*===================================================================
  986. CAppln::Restart
  987. Restart an application. (used for when global.asa changes or
  988. debugging enable metabase key changes)
  989. ===================================================================*/
  990. HRESULT CAppln::Restart(BOOL fForceRestart /* = FALSE*/)
  991. {
  992. AddRef(); // keep addref'd while restarting
  993. DBGPRINTF((DBG_CONTEXT, "Restarting application %S, %p\n", m_pszMetabaseKey, this));
  994. g_ApplnMgr.Lock();
  995. // If already restarted or
  996. // in the tombstone state or
  997. // restart not allowed
  998. // shutting down -> don't restart
  999. if (m_fGlobalChanged ||
  1000. m_fTombstone ||
  1001. (!m_pAppConfig->fEnableApplicationRestart() && !fForceRestart) ||
  1002. IsShutDownInProgress())
  1003. {
  1004. // Give back the lock and refcount
  1005. // since we don't need them
  1006. g_ApplnMgr.UnLock();
  1007. Release();
  1008. return S_OK;
  1009. }
  1010. // remove the application from the global hash
  1011. CLinkElem *pLinkElem = g_ApplnMgr.DeleteElem
  1012. (
  1013. m_pszMetabaseKey,
  1014. _tcslen(m_pszMetabaseKey) * sizeof(TCHAR)
  1015. );
  1016. Assert(pLinkElem);
  1017. Assert(static_cast<CAppln *>(pLinkElem) == this);
  1018. // Unlock
  1019. g_ApplnMgr.UnLock();
  1020. // Indicate to Delete All Sessions
  1021. m_fGlobalChanged = TRUE;
  1022. // Increment the count of restarting applications
  1023. InterlockedIncrement((LPLONG)&g_nApplicationsRestarting);
  1024. // Increment the count of restarted applications
  1025. InterlockedIncrement((LPLONG)&g_nApplicationsRestarted);
  1026. m_pSessionMgr->UnScheduleSessionKiller();
  1027. // cleanup the directory monitor entries
  1028. if (FIsWinNT())
  1029. {
  1030. Lock(); // Place critical Section around access to m_rgpvDME
  1031. while ((m_rgpvDME).Count())
  1032. {
  1033. static_cast<CDirMonitorEntry *>(m_rgpvDME[0])->Release();
  1034. (m_rgpvDME).Remove(0);
  1035. }
  1036. m_rgpvDME.Clear();
  1037. UnLock();
  1038. }
  1039. // add this application to the CleanupManager...
  1040. g_ApplnCleanupMgr.AddAppln(this);
  1041. return S_OK;
  1042. }
  1043. /*===================================================================
  1044. CAppln::ApplnCleanupProc
  1045. Called by the g_ApplnCleanupMgr thread to complete cleanup
  1046. ===================================================================*/
  1047. DWORD __stdcall CAppln::ApplnCleanupProc(VOID *pArg)
  1048. {
  1049. CAppln *pAppln = (CAppln *)pArg;
  1050. DBGPRINTF((DBG_CONTEXT, "[ApplnCleanupProc] enterred for %S, %p\n", pAppln->m_pszMetabaseKey, pArg));
  1051. // Let the requests to drain while trying to delete sessions
  1052. while (!IsShutDownInProgress() && (pAppln->m_cRequests || pAppln->m_cSessions))
  1053. {
  1054. if (pAppln->m_cSessions)
  1055. pAppln->m_pSessionMgr->DeleteAllSessions(FALSE);
  1056. if (pAppln->m_cSessions || pAppln->m_cRequests)
  1057. Sleep(200);
  1058. }
  1059. g_ApplnMgr.DeleteApplicationIfExpired(pAppln);
  1060. // Decrement the count of restarting applications
  1061. InterlockedDecrement((LPLONG)&g_nApplicationsRestarting);
  1062. // Decrement the count of restart threads
  1063. InterlockedDecrement(&g_nAppRestartThreads);
  1064. // tell the cleanup manager to check for more work
  1065. g_ApplnCleanupMgr.Wakeup();
  1066. pAppln->Release();
  1067. return 0;
  1068. }
  1069. /*===================================================================
  1070. CAppln::UnInit
  1071. Convert to tombstone state
  1072. Parameters:
  1073. NONE
  1074. Returns:
  1075. HRESULT (S_OK)
  1076. ===================================================================*/
  1077. HRESULT CAppln::UnInit()
  1078. {
  1079. Assert(!m_fTombstone); // don't do it twice
  1080. #ifdef DBG_NOTIFICATION
  1081. #if UNICODE
  1082. DBGPRINTF((DBG_CONTEXT, "Uniniting application %S, %p\n", m_pszApplnPath, this));
  1083. #else
  1084. DBGPRINTF((DBG_CONTEXT, "Uniniting application %s, %p\n", m_pszApplnPath, this));
  1085. #endif
  1086. #endif // DBG_NOTIFICATION
  1087. // Flush the global.asa from the script engine cache
  1088. if (m_pszGlobalAsa)
  1089. {
  1090. g_ScriptManager.FlushCache(m_pszGlobalAsa);
  1091. }
  1092. if (m_pGlobalTemplate)
  1093. {
  1094. // Keep template (and inc file) cache locked while releasing
  1095. // GLOBAL.ASA template so that it wouldn't step onto Flush logic
  1096. //
  1097. // NOTE: CTemplate::End potentially queues global.asa for cleanup on
  1098. // our thread! CleanupEngines() must therefore be called
  1099. // *after* this step.
  1100. //
  1101. LockTemplateAndIncFileCaches();
  1102. m_pGlobalTemplate->End();
  1103. UnLockTemplateAndIncFileCaches();
  1104. m_pGlobalTemplate = NULL;
  1105. }
  1106. //If NT, remove this app from any file/appln mappings it may be in
  1107. if (FIsWinNT())
  1108. {
  1109. g_FileAppMap.Lock();
  1110. int i = m_rgpvFileAppln.Count();
  1111. while (i > 0)
  1112. {
  1113. #ifdef DBG_NOTIFICATION
  1114. DBGPRINTF((DBG_CONTEXT, "Removing application from File/App mapping\n"));
  1115. #endif // DBG_NOTIFICATION
  1116. static_cast<CFileApplnList *>(m_rgpvFileAppln[0])->RemoveApplication(this);
  1117. m_rgpvFileAppln.Remove(0);
  1118. i--;
  1119. }
  1120. g_FileAppMap.UnLock();
  1121. m_rgpvFileAppln.Clear();
  1122. Lock(); // Protecting m_rqpvDME with a critical section
  1123. m_rgpvDME.Clear();
  1124. UnLock();
  1125. // If debuggable application, clean up pending scripts
  1126. if (m_fDebuggable)
  1127. g_ApplnMgr.CleanupEngines();
  1128. }
  1129. // Free the properties collection
  1130. if (m_pProperties)
  1131. {
  1132. m_pProperties->UnInit();
  1133. m_pProperties->Release();
  1134. m_pProperties = NULL;
  1135. }
  1136. // Free the tagged objects collection
  1137. if (m_pTaggedObjects)
  1138. {
  1139. m_pTaggedObjects->UnInit();
  1140. m_pTaggedObjects->Release();
  1141. m_pTaggedObjects = NULL;
  1142. }
  1143. // Before we close down, debuggable templates need to be made non-debuggable
  1144. if (m_fDebuggable)
  1145. g_TemplateCache.RemoveApplicationFromDebuggerUI(this);
  1146. if (m_pAppRoot)
  1147. {
  1148. m_pAppRoot->Detach();
  1149. m_pAppRoot->Close();
  1150. m_pAppRoot->Release();
  1151. m_pAppRoot = NULL;
  1152. }
  1153. if (m_pApplCompCol)
  1154. {
  1155. delete m_pApplCompCol;
  1156. m_pApplCompCol = NULL;
  1157. }
  1158. if (m_pActivity)
  1159. {
  1160. delete m_pActivity;
  1161. m_pActivity = NULL;
  1162. }
  1163. if (m_pSessionMgr)
  1164. {
  1165. delete m_pSessionMgr;
  1166. m_pSessionMgr = NULL;
  1167. }
  1168. if (m_pAppConfig)
  1169. {
  1170. /*
  1171. * BUG 89144: Uninit AppConfig but do it from the MTA
  1172. * When AppConfig is inited, it is done on a WAM thread. WAM
  1173. * threads are MTA threads. At that time we register an event
  1174. * sink to get Metabase change notifications. Now, during shutdown,
  1175. * we are running on an ASP worker thread, which is an STA thread.
  1176. * That means we will get an RPC_E_WRONGTHREAD error shutting down. The
  1177. * fix is to make the uninit call happen on an MTA thread.
  1178. */
  1179. HRESULT hr;
  1180. HRESULT AppConfigUnInit(void *pV1, void *pV2);
  1181. HANDLE hCompletionEvent = CreateEvent(NULL, FALSE, FALSE, NULL);
  1182. hr = CallMTACallback
  1183. (
  1184. AppConfigUnInit,
  1185. m_pAppConfig,
  1186. hCompletionEvent
  1187. );
  1188. Assert(SUCCEEDED(hr));
  1189. WaitForSingleObject(hCompletionEvent, INFINITE);
  1190. CloseHandle(hCompletionEvent);
  1191. delete m_pAppConfig;
  1192. m_pAppConfig = NULL;
  1193. }
  1194. if (m_pdispGlobTypeLibWrapper)
  1195. {
  1196. m_pdispGlobTypeLibWrapper->Release();
  1197. m_pdispGlobTypeLibWrapper = NULL;
  1198. }
  1199. if (m_pszGlobalAsa)
  1200. {
  1201. // If there was a change notification on global.asa
  1202. // then flush the template now.
  1203. // UNDONE: flush correct global.asa
  1204. if (m_fGlobalChanged)
  1205. g_TemplateCache.Flush(m_pszGlobalAsa, MATCH_ALL_INSTANCE_IDS);
  1206. delete [] m_pszGlobalAsa;
  1207. m_pszGlobalAsa = NULL;
  1208. }
  1209. if (m_pszMetabaseKey)
  1210. {
  1211. delete [] m_pszMetabaseKey;
  1212. m_pszMetabaseKey = NULL;
  1213. }
  1214. if (m_pszApplnPath)
  1215. {
  1216. delete [] m_pszApplnPath;
  1217. m_pszApplnPath = NULL;
  1218. }
  1219. if (m_pszApplnVRoot)
  1220. {
  1221. delete [] m_pszApplnVRoot;
  1222. m_pszApplnVRoot = NULL;
  1223. }
  1224. if (FIsWinNT() && m_fUseImpersonationHandle)
  1225. {
  1226. CloseHandle(m_hUserImpersonation);
  1227. m_hUserImpersonation = NULL;
  1228. }
  1229. if (m_fInited)
  1230. {
  1231. DeleteCriticalSection(&m_csInternalLock);
  1232. DeleteCriticalSection(&m_csApplnLock);
  1233. }
  1234. if (m_pServicesConfig)
  1235. m_pServicesConfig->Release();
  1236. // Mark this application as Tombstone
  1237. m_fTombstone = TRUE;
  1238. InterlockedDecrement((LPLONG)&g_nApplications);
  1239. // Disconnennect from proxies (in case we are shutting down or will shortly shut down)
  1240. CoDisconnectObject(static_cast<IApplicationObject *>(this), 0);
  1241. return S_OK;
  1242. }
  1243. /*===================================================================
  1244. CAppln::BindToActivity
  1245. Creates application level activity either
  1246. as a clone of the given activity or
  1247. as a brand new activity
  1248. Must be called within critical section. Does not lock itself.
  1249. Parameters:
  1250. CViperActivity *pActivity activity to clone (could be NULL)
  1251. Returns:
  1252. NONE
  1253. ===================================================================*/
  1254. HRESULT CAppln::BindToActivity
  1255. (
  1256. CViperActivity *pActivity
  1257. )
  1258. {
  1259. if (m_pActivity)
  1260. {
  1261. // multiple requests to bind to new activity are ok
  1262. if (!pActivity)
  1263. return S_OK;
  1264. // but not to clone from an existing activity
  1265. Assert(FALSE);
  1266. return E_FAIL;
  1267. }
  1268. m_pActivity = new CViperActivity;
  1269. if (!m_pActivity)
  1270. return E_OUTOFMEMORY;
  1271. HRESULT hr;
  1272. if (pActivity)
  1273. hr = m_pActivity->InitClone(pActivity);
  1274. else
  1275. hr = m_pActivity->Init(m_pServicesConfig);
  1276. if (FAILED(hr))
  1277. {
  1278. delete m_pActivity;
  1279. m_pActivity = NULL;
  1280. }
  1281. return hr;
  1282. }
  1283. /*===================================================================
  1284. CAppln::SetGlobalAsa
  1285. Remembers GLOBAL.ASA file path for this application
  1286. Parameters:
  1287. const char *pszGlobalAsa path to (copy and) remember
  1288. Returns:
  1289. HRESULT
  1290. ===================================================================*/
  1291. HRESULT CAppln::SetGlobalAsa
  1292. (
  1293. const TCHAR *pszGlobalAsa
  1294. )
  1295. {
  1296. // remove existing
  1297. if (m_pszGlobalAsa)
  1298. {
  1299. delete [] m_pszGlobalAsa;
  1300. m_pszGlobalAsa = NULL;
  1301. }
  1302. // store new
  1303. if (pszGlobalAsa)
  1304. {
  1305. DWORD cch = _tcslen(pszGlobalAsa);
  1306. DWORD cb = (cch + 1) * sizeof(TCHAR);
  1307. m_pszGlobalAsa = new TCHAR[cch+1];
  1308. if (!m_pszGlobalAsa)
  1309. return E_OUTOFMEMORY;
  1310. memcpy(m_pszGlobalAsa, pszGlobalAsa, cb);
  1311. }
  1312. return S_OK;
  1313. }
  1314. /*===================================================================
  1315. CAppln::AddDirMonitorEntry
  1316. Remembers change notifcation monitor entries for this application
  1317. Parameters:
  1318. pDirMonitorEntry pointer to DME
  1319. Returns:
  1320. S_OK if the monitor entry was added to the list
  1321. ===================================================================*/
  1322. HRESULT CAppln::AddDirMonitorEntry(CDirMonitorEntry *pDirMonitorEntry)
  1323. {
  1324. DBG_ASSERT(m_fInited);
  1325. DBG_ASSERT(pDirMonitorEntry);
  1326. HRESULT hr = S_OK;
  1327. // Add the DME to the list
  1328. Lock(); // Protect m_rgpvDME by critical section
  1329. if (FAILED(hr = m_rgpvDME.Append(pDirMonitorEntry)))
  1330. {
  1331. pDirMonitorEntry->Release();
  1332. }
  1333. UnLock();
  1334. return hr;
  1335. }
  1336. /*===================================================================
  1337. CAppln::AddFileApplnEntry
  1338. Remembers change notifcation monitor entries for this application
  1339. Parameters:
  1340. pFileAppln pointer to FileApplnEntry
  1341. Returns:
  1342. S_OK if the monitor entry was added to the list
  1343. S_FALSE if the monitor entry was alread in the list
  1344. ===================================================================*/
  1345. HRESULT CAppln::AddFileApplnEntry(CFileApplnList *pFileAppln)
  1346. {
  1347. DBG_ASSERT(m_fInited);
  1348. DBG_ASSERT(pFileAppln);
  1349. HRESULT hr = S_OK;
  1350. int index;
  1351. // See if the file/application entry is alreay in the list
  1352. hr = m_rgpvFileAppln.Find(pFileAppln, &index);
  1353. if (hr == S_FALSE)
  1354. {
  1355. // Add the file/application entry to the list
  1356. hr = m_rgpvFileAppln.Append(pFileAppln);
  1357. }
  1358. else
  1359. {
  1360. // The file/application entry was already in the list
  1361. hr = S_FALSE;
  1362. }
  1363. return hr;
  1364. }
  1365. /*===================================================================
  1366. CAppln::QueryInterface
  1367. QueryInterface() -- IApplicationObject implementation.
  1368. Parameters:
  1369. REFIID riid
  1370. void **ppv
  1371. Returns:
  1372. HRESULT
  1373. ===================================================================*/
  1374. STDMETHODIMP CAppln::QueryInterface
  1375. (
  1376. REFIID riid,
  1377. void **ppv
  1378. )
  1379. {
  1380. *ppv = NULL;
  1381. if (IID_IUnknown == riid ||
  1382. IID_IDispatch == riid ||
  1383. IID_IApplicationObject == riid ||
  1384. IID_IDenaliIntrinsic == riid)
  1385. {
  1386. *ppv = static_cast<IApplicationObject *>(this);
  1387. }
  1388. else if (IID_ISupportErrorInfo == riid)
  1389. {
  1390. *ppv = &m_ISuppErrImp;
  1391. }
  1392. else if (IID_IMarshal == riid)
  1393. {
  1394. *ppv = static_cast<IMarshal *>(this);
  1395. }
  1396. if (*ppv)
  1397. {
  1398. ((LPUNKNOWN)*ppv)->AddRef();
  1399. return S_OK;
  1400. }
  1401. return E_NOINTERFACE;
  1402. }
  1403. /*===================================================================
  1404. CAppln::AddRef
  1405. AddRef() -- IUnknown implementation.
  1406. Parameters:
  1407. Returns:
  1408. Ref count
  1409. ===================================================================*/
  1410. STDMETHODIMP_(ULONG) CAppln::AddRef() {
  1411. DWORD cRefs = InterlockedIncrement((LPLONG)&m_cRefs);
  1412. IF_DEBUG(APPLICATION) {
  1413. WriteRefTraceLog(gm_pTraceLog, cRefs, this);
  1414. }
  1415. return cRefs;
  1416. }
  1417. /*===================================================================
  1418. CAppln::Release
  1419. Release() -- IUnknown implementation.
  1420. Parameters:
  1421. Returns:
  1422. Ref count
  1423. ===================================================================*/
  1424. STDMETHODIMP_(ULONG) CAppln::Release()
  1425. {
  1426. DWORD cRefs = InterlockedDecrement((LPLONG)&m_cRefs);
  1427. IF_DEBUG(APPLICATION) {
  1428. WriteRefTraceLog(gm_pTraceLog, cRefs, this);
  1429. }
  1430. if (cRefs)
  1431. return cRefs;
  1432. delete this;
  1433. return 0;
  1434. }
  1435. /*===================================================================
  1436. CAppln::CheckForTombstone
  1437. Tombstone stub for IApplicationObject methods. If the object is
  1438. tombstone, does ExceptionId and fails.
  1439. Parameters:
  1440. Returns:
  1441. HRESULT E_FAIL if Tombstone
  1442. S_OK if not
  1443. ===================================================================*/
  1444. HRESULT CAppln::CheckForTombstone()
  1445. {
  1446. if (!m_fTombstone)
  1447. return S_OK;
  1448. ExceptionId
  1449. (
  1450. IID_IApplicationObject,
  1451. IDE_APPLICATION,
  1452. IDE_INTRINSIC_OUT_OF_SCOPE
  1453. );
  1454. return E_FAIL;
  1455. }
  1456. /*===================================================================
  1457. CAppln::Lock
  1458. IApplicationObject method.
  1459. Will allow the user to lock the application intrinsic for the
  1460. purpose of adding/deleting values.
  1461. Parameters:
  1462. NONE
  1463. Returns:
  1464. HRESULT S_OK on success
  1465. E_FAIL otherwise
  1466. ===================================================================*/
  1467. STDMETHODIMP CAppln::Lock()
  1468. {
  1469. if (FAILED(CheckForTombstone()))
  1470. return E_FAIL;
  1471. Assert(m_fInited);
  1472. DWORD dwId = GetCurrentThreadId();
  1473. // If this thread already has the lock, increment lock ref count
  1474. if (m_dwLockThreadID == dwId)
  1475. {
  1476. m_cLockRefCount++;
  1477. }
  1478. else
  1479. {
  1480. EnterCriticalSection(&m_csApplnLock);
  1481. m_cLockRefCount = 1;
  1482. m_dwLockThreadID = dwId;
  1483. }
  1484. return S_OK;
  1485. }
  1486. /*===================================================================
  1487. CAppln::UnLock
  1488. IApplicationObject method.
  1489. Will allow the user to unlock the application intrinsic only
  1490. if it has been locked by this user.
  1491. Parameters:
  1492. NONE
  1493. Returns:
  1494. HRESULT S_OK
  1495. ===================================================================*/
  1496. STDMETHODIMP CAppln::UnLock()
  1497. {
  1498. if (FAILED(CheckForTombstone()))
  1499. return E_FAIL;
  1500. if (m_dwLockThreadID == GetCurrentThreadId())
  1501. {
  1502. if (--m_cLockRefCount == 0)
  1503. {
  1504. // Unlock the application
  1505. m_dwLockThreadID = INVALID_THREADID;
  1506. LeaveCriticalSection(&m_csApplnLock);
  1507. }
  1508. }
  1509. return S_OK;
  1510. }
  1511. /*===================================================================
  1512. CAppln::UnLockAfterRequest
  1513. Remove any application locks left by the user script
  1514. Parameters:
  1515. NONE
  1516. Returns:
  1517. HRESULT S_OK
  1518. ===================================================================*/
  1519. HRESULT CAppln::UnLockAfterRequest()
  1520. {
  1521. Assert(!m_fTombstone);
  1522. if (m_cLockRefCount > 0 && m_dwLockThreadID == GetCurrentThreadId())
  1523. {
  1524. m_cLockRefCount = 0;
  1525. m_dwLockThreadID = INVALID_THREADID;
  1526. LeaveCriticalSection(&m_csApplnLock);
  1527. }
  1528. return S_OK;
  1529. }
  1530. /*===================================================================
  1531. CAppln::get_Value
  1532. IApplicationObject method.
  1533. Will allow the user to retreive a application state variable,
  1534. the variable will come as a named pair, bstr is the name and
  1535. var is the value or object to be returned for that name
  1536. Parameters:
  1537. BSTR FAR * bstrName Name of the variable to get
  1538. VARIANT * pVar Value/object to get for the variable
  1539. Returns:
  1540. HRESULT S_OK on success
  1541. ===================================================================*/
  1542. STDMETHODIMP CAppln::get_Value
  1543. (
  1544. BSTR bstrName,
  1545. VARIANT *pVar
  1546. )
  1547. {
  1548. if (FAILED(CheckForTombstone()))
  1549. return E_FAIL;
  1550. if (bstrName == NULL)
  1551. {
  1552. ExceptionId(IID_IApplicationObject,
  1553. IDE_APPLICATION, IDE_EXPECTING_STR);
  1554. return E_FAIL;
  1555. }
  1556. VariantInit(pVar); // default variant empty
  1557. WCHAR *pwszName;
  1558. STACK_BUFFER(rgbName, 42);
  1559. WSTR_STACK_DUP(bstrName, &rgbName, &pwszName);
  1560. if (pwszName == NULL)
  1561. return S_OK; // no name - no value - no error
  1562. //_wcsupr(pwszName);
  1563. Assert(m_pApplCompCol);
  1564. HRESULT hr = S_OK;
  1565. CComponentObject *pObj = NULL;
  1566. // Lock the application
  1567. Lock();
  1568. hr = m_pApplCompCol->GetProperty(pwszName, &pObj);
  1569. if (SUCCEEDED(hr))
  1570. {
  1571. Assert(pObj);
  1572. hr = pObj->GetVariant(pVar);
  1573. }
  1574. // UnLock the application
  1575. UnLock();
  1576. return S_OK;
  1577. }
  1578. /*===================================================================
  1579. CAppln::putref_Value
  1580. IApplicationObject method.
  1581. Will allow the user to assign a application state variable to be saved
  1582. the variable will come as a named pair, bstr is the name and
  1583. var is the value or object to be stored for that name
  1584. Parameters:
  1585. BSTR bstrName Name of the variable to set
  1586. VARIANT Var Value/object to set for the variable
  1587. Returns:
  1588. HRESULT S_OK on success
  1589. ===================================================================*/
  1590. STDMETHODIMP CAppln::putref_Value
  1591. (
  1592. BSTR bstrName,
  1593. VARIANT Var
  1594. )
  1595. {
  1596. if (FAILED(CheckForTombstone()))
  1597. return E_FAIL;
  1598. if (FIsIntrinsic(&Var))
  1599. {
  1600. ExceptionId(IID_IApplicationObject, IDE_APPLICATION,
  1601. IDE_APPLICATION_CANT_STORE_INTRINSIC);
  1602. return E_FAIL;
  1603. }
  1604. if (bstrName == NULL)
  1605. {
  1606. ExceptionId(IID_IApplicationObject,
  1607. IDE_APPLICATION, IDE_EXPECTING_STR);
  1608. return E_FAIL;
  1609. }
  1610. HRESULT hr;
  1611. Assert(m_pApplCompCol);
  1612. // Prepare property name
  1613. WCHAR *pwszName;
  1614. STACK_BUFFER(rgbName, 42);
  1615. WSTR_STACK_DUP(bstrName, &rgbName, &pwszName);
  1616. if (pwszName == NULL)
  1617. {
  1618. ExceptionId(IID_IApplicationObject,
  1619. IDE_APPLICATION, IDE_EXPECTING_STR);
  1620. return E_FAIL;
  1621. }
  1622. //_wcsupr(pwszName);
  1623. // Lock the application
  1624. Lock();
  1625. hr = m_pApplCompCol->AddProperty(pwszName, &Var);
  1626. // Unlock the application
  1627. UnLock();
  1628. if (hr == RPC_E_WRONG_THREAD)
  1629. {
  1630. // We use RPC_E_WRONG_THREAD to indicate bad model object
  1631. ExceptionId(IID_IApplicationObject,
  1632. IDE_APPLICATION, IDE_APPLICATION_CANT_STORE_OBJECT);
  1633. hr = E_FAIL;
  1634. }
  1635. return hr;
  1636. }
  1637. /*===================================================================
  1638. CAppln::put_Value
  1639. IApplicationObject method.
  1640. Implement property put by dereferencing variants before
  1641. calling putref.
  1642. Parameters:
  1643. BSTR FAR * bstrName Name of the variable to set
  1644. VARIANT Var Value/object to set for the variable
  1645. Returns:
  1646. HRESULT S_OK on success
  1647. ===================================================================*/
  1648. STDMETHODIMP CAppln::put_Value
  1649. (
  1650. BSTR bstrName,
  1651. VARIANT Var
  1652. )
  1653. {
  1654. if (FAILED(CheckForTombstone()))
  1655. return E_FAIL;
  1656. if (bstrName == NULL)
  1657. {
  1658. ExceptionId(IID_IApplicationObject,
  1659. IDE_APPLICATION, IDE_EXPECTING_STR);
  1660. return E_FAIL;
  1661. }
  1662. HRESULT hr;
  1663. Assert(m_pApplCompCol);
  1664. // Prepare property name
  1665. WCHAR *pwszName;
  1666. STACK_BUFFER(rgbName, 42);
  1667. WSTR_STACK_DUP(bstrName, &rgbName, &pwszName);
  1668. if (pwszName == NULL)
  1669. {
  1670. ExceptionId(IID_IApplicationObject,
  1671. IDE_APPLICATION, IDE_EXPECTING_STR);
  1672. return E_FAIL;
  1673. }
  1674. //_wcsupr(pwszName);
  1675. // Lock the application
  1676. Lock();
  1677. VARIANT varResolved;
  1678. hr = VariantResolveDispatch(&varResolved, &Var,
  1679. IID_IApplicationObject,
  1680. IDE_APPLICATION);
  1681. if (SUCCEEDED(hr))
  1682. {
  1683. hr = m_pApplCompCol->AddProperty(pwszName, &varResolved);
  1684. VariantClear(&varResolved);
  1685. }
  1686. // Unlock the application
  1687. UnLock();
  1688. if (hr == RPC_E_WRONG_THREAD)
  1689. {
  1690. // We use RPC_E_WRONG_THREAD to indicate bad model object
  1691. ExceptionId(IID_IApplicationObject,
  1692. IDE_APPLICATION, IDE_APPLICATION_CANT_STORE_OBJECT);
  1693. hr = E_FAIL;
  1694. }
  1695. return hr;
  1696. }
  1697. /*===================================================================
  1698. CAppln::get_Contents
  1699. Return the application contents dictionary
  1700. ===================================================================*/
  1701. STDMETHODIMP CAppln::get_Contents(IVariantDictionary **ppDictReturn)
  1702. {
  1703. if (FAILED(CheckForTombstone()) || !m_pProperties)
  1704. return E_FAIL;
  1705. return m_pProperties->QueryInterface(IID_IVariantDictionary, reinterpret_cast<void **>(ppDictReturn));
  1706. }
  1707. /*===================================================================
  1708. CAppln::get_StaticObjects
  1709. Return the application static objects dictionary
  1710. ===================================================================*/
  1711. STDMETHODIMP CAppln::get_StaticObjects(IVariantDictionary **ppDictReturn)
  1712. {
  1713. if (FAILED(CheckForTombstone()) || !m_pTaggedObjects)
  1714. return E_FAIL;
  1715. return m_pTaggedObjects->QueryInterface(IID_IVariantDictionary, reinterpret_cast<void **>(ppDictReturn));
  1716. }
  1717. /*===================================================================
  1718. CAppln::UpdateConfig
  1719. Updates configuration from metabase if needed
  1720. ===================================================================*/
  1721. HRESULT CAppln::UpdateConfig(CIsapiReqInfo *pIReq, BOOL *pfRestart, BOOL *pfFlushAll)
  1722. {
  1723. BOOL fRestart = FALSE;
  1724. BOOL fFlushAll = FALSE;
  1725. if (m_pAppConfig->fNeedUpdate())
  1726. {
  1727. InternalLock();
  1728. if (m_pAppConfig->fNeedUpdate()) // still need update?
  1729. {
  1730. BOOL fAllowedDebugging = m_pAppConfig->fAllowDebugging();
  1731. BOOL fAllowedClientDebug = m_pAppConfig->fAllowClientDebug();
  1732. BOOL fAllowedRestart = m_pAppConfig->fEnableApplicationRestart();
  1733. BOOL fParentPathsEnabled = m_pAppConfig->fEnableParentPaths();
  1734. UINT uLastCodePage = m_pAppConfig->uCodePage();
  1735. LCID uLastLCID = m_pAppConfig->uLCID();
  1736. BOOL fPrevSxsEnabled = m_pAppConfig->fSxsEnabled();
  1737. BOOL fPrevUsePartition = m_pAppConfig->fUsePartition();
  1738. BOOL fPrevUseTracker = m_pAppConfig->fTrackerEnabled();
  1739. BOOL fRestartEnabledUpdated = m_pAppConfig->fRestartEnabledUpdated();
  1740. char szLastDefaultEngine[64];
  1741. strncpy(szLastDefaultEngine, m_pAppConfig->szScriptLanguage(), sizeof szLastDefaultEngine);
  1742. szLastDefaultEngine[sizeof(szLastDefaultEngine) - 1] = '\0';
  1743. m_pAppConfig->Update(pIReq);
  1744. BOOL fAllowDebugging = m_pAppConfig->fAllowDebugging();
  1745. BOOL fAllowClientDebug = m_pAppConfig->fAllowClientDebug();
  1746. BOOL fAllowRestart = m_pAppConfig->fEnableApplicationRestart();
  1747. BOOL fEnableParentPaths = m_pAppConfig->fEnableParentPaths();
  1748. UINT uCodePage = m_pAppConfig->uCodePage();
  1749. LCID uLCID = m_pAppConfig->uLCID();
  1750. BOOL fCurSxsEnabled = m_pAppConfig->fSxsEnabled();
  1751. BOOL fCurUsePartition = m_pAppConfig->fUsePartition();
  1752. BOOL fCurUseTracker = m_pAppConfig->fTrackerEnabled();
  1753. const char *szNewDefaultEngine = m_pAppConfig->szScriptLanguage();
  1754. fFlushAll = strcmpi(szLastDefaultEngine, szNewDefaultEngine) != 0
  1755. || (fParentPathsEnabled != fEnableParentPaths)
  1756. || (uLastCodePage != uCodePage)
  1757. || (uLastLCID != uLCID);
  1758. fRestart = (fAllowDebugging != fAllowedDebugging) ||
  1759. (fAllowClientDebug != fAllowedClientDebug) ||
  1760. ((fAllowRestart != fAllowedRestart) && fAllowRestart) ||
  1761. ((fAllowRestart == fAllowedRestart) && fRestartEnabledUpdated) ||
  1762. (fCurSxsEnabled != fPrevSxsEnabled) ||
  1763. (fCurUsePartition != fPrevUsePartition) ||
  1764. (fCurUseTracker != fPrevUseTracker) ||
  1765. fFlushAll;
  1766. }
  1767. InternalUnLock();
  1768. }
  1769. if (pfRestart)
  1770. *pfRestart = fRestart;
  1771. if (pfFlushAll)
  1772. *pfFlushAll = fFlushAll;
  1773. return S_OK;
  1774. }
  1775. /*===================================================================
  1776. CAppln::FPathMonitored()
  1777. Checks the list of DMEs in application to see if the specified path
  1778. is already being monitored.
  1779. ===================================================================*/
  1780. CASPDirMonitorEntry *CAppln::FPathMonitored(LPCTSTR pszPath)
  1781. {
  1782. int i;
  1783. Lock(); // Protect m_rqpvDME by a critical section
  1784. int cDMEs = m_rgpvDME.Count();
  1785. for (i=0; i < cDMEs; i++) {
  1786. CASPDirMonitorEntry *pDME = static_cast<CASPDirMonitorEntry *>(m_rgpvDME[i]);
  1787. if (pDME == NULL)
  1788. break;
  1789. if (pDME->FPathMonitored(pszPath))
  1790. {
  1791. UnLock();
  1792. return pDME;
  1793. }
  1794. }
  1795. UnLock();
  1796. return NULL;
  1797. }
  1798. #ifdef DBG
  1799. /*===================================================================
  1800. CAppln::AssertValid
  1801. Test to make sure that the CAppln object is currently correctly
  1802. formed and assert if it is not.
  1803. Returns:
  1804. Nothing
  1805. Side effects:
  1806. None.
  1807. ===================================================================*/
  1808. void CAppln::AssertValid() const
  1809. {
  1810. Assert(m_fInited);
  1811. Assert(m_pSessionMgr);
  1812. Assert(m_pApplCompCol);
  1813. m_pApplCompCol->AssertValid();
  1814. }
  1815. #endif // DBG
  1816. /*===================================================================
  1817. C A p p l n M g r
  1818. ===================================================================*/
  1819. /*===================================================================
  1820. CApplnMgr::CApplnMgr
  1821. Application Manager constructor.
  1822. Parameters:
  1823. NONE
  1824. Returns:
  1825. NONE
  1826. ===================================================================*/
  1827. CApplnMgr::CApplnMgr()
  1828. : m_fInited(FALSE),
  1829. m_fHashTableInited(FALSE), m_fCriticalSectionInited(FALSE)
  1830. {
  1831. }
  1832. /*===================================================================
  1833. CApplnMgr::~CApplnMgr
  1834. Application Manager destructor.
  1835. Parameters:
  1836. NONE
  1837. Returns:
  1838. NONE
  1839. ===================================================================*/
  1840. CApplnMgr::~CApplnMgr()
  1841. {
  1842. if (!m_fInited)
  1843. UnInit();
  1844. }
  1845. /*===================================================================
  1846. HRESULT CApplnMgr::Init
  1847. Initializes the Appln Manager.
  1848. Parameters:
  1849. NONE
  1850. Returns:
  1851. S_OK Success
  1852. E_FAIL Failure
  1853. E_OUTOFMEMORY Out of memory
  1854. ===================================================================*/
  1855. HRESULT CApplnMgr::Init( void )
  1856. {
  1857. HRESULT hr = S_OK;
  1858. Assert(!m_fInited);
  1859. // Init hash table
  1860. hr = CHashTable::Init(NUM_APPLMGR_HASHING_BUCKETS);
  1861. if (FAILED(hr))
  1862. return hr;
  1863. m_fHashTableInited = TRUE;
  1864. // Init critical section
  1865. ErrInitCriticalSection(&m_csLock, hr);
  1866. if (FAILED(hr))
  1867. return(hr);
  1868. m_fCriticalSectionInited = TRUE;
  1869. m_fInited = TRUE;
  1870. return g_ApplnCleanupMgr.Init();
  1871. }
  1872. /*===================================================================
  1873. HRESULT CApplnMgr::UnInit
  1874. UnInitializes the Appln Manager.
  1875. Parameters:
  1876. NONE
  1877. Returns:
  1878. S_OK Success
  1879. E_FAIL Failure
  1880. ===================================================================*/
  1881. HRESULT CApplnMgr::UnInit( void )
  1882. {
  1883. if (m_fHashTableInited)
  1884. {
  1885. CHashTable::UnInit();
  1886. m_fHashTableInited = FALSE;
  1887. }
  1888. if (m_fCriticalSectionInited)
  1889. {
  1890. DeleteCriticalSection(&m_csLock);
  1891. m_fCriticalSectionInited = FALSE;
  1892. }
  1893. m_fInited = FALSE;
  1894. return g_ApplnCleanupMgr.UnInit();
  1895. }
  1896. /*===================================================================
  1897. CApplnMgr::AddAppln
  1898. Adds a CAppln element to link list / hash table.
  1899. User has to check if Appln already exists before calling this.
  1900. Critical sectioning is in CHitObj::BrowserRequestInit().
  1901. Parameters:
  1902. char *pszApplnKey Application metabase key
  1903. char *pszApplnPath Application directory path
  1904. CIsapiReqInfo *pIReq
  1905. HANDLE hUserImpersonation impersonation handle
  1906. CAppln **ppAppln [out] Application created
  1907. Returns:
  1908. HRESULT
  1909. ===================================================================*/
  1910. HRESULT CApplnMgr::AddAppln
  1911. (
  1912. TCHAR *pszApplnKey,
  1913. TCHAR *pszApplnPath,
  1914. CIsapiReqInfo *pIReq,
  1915. HANDLE hUserImpersonation,
  1916. CAppln **ppAppln
  1917. )
  1918. {
  1919. *ppAppln = NULL; // return NULL if failed
  1920. // Create CAppln object
  1921. CAppln *pAppln = new CAppln;
  1922. if (!pAppln)
  1923. return E_OUTOFMEMORY;
  1924. // Init CAppln object
  1925. HRESULT hr;
  1926. hr = pAppln->Init
  1927. (
  1928. pszApplnKey,
  1929. pszApplnPath,
  1930. pIReq,
  1931. hUserImpersonation
  1932. );
  1933. if (FAILED(hr))
  1934. {
  1935. pAppln->UnInit();
  1936. pAppln->Release();
  1937. return hr;
  1938. }
  1939. // Add to hash table
  1940. if (!CHashTable::AddElem(pAppln))
  1941. {
  1942. pAppln->UnInit();
  1943. pAppln->Release();
  1944. return E_FAIL;
  1945. }
  1946. *ppAppln = pAppln;
  1947. return S_OK;
  1948. }
  1949. /*===================================================================
  1950. CApplnMgr::FindAppln
  1951. Finds CAppln in hash table
  1952. Critical sectioning must be done outside
  1953. Parameters:
  1954. char *pszApplnKey Application metabase key
  1955. CAppln **ppAppln [out] Application found
  1956. Returns:
  1957. S_OK if found
  1958. S_FALSE if not found
  1959. ===================================================================*/
  1960. HRESULT CApplnMgr::FindAppln
  1961. (
  1962. TCHAR *pszApplnKey,
  1963. CAppln **ppAppln
  1964. )
  1965. {
  1966. CLinkElem *pLinkElem = CHashTable::FindElem
  1967. (
  1968. pszApplnKey,
  1969. _tcslen(pszApplnKey)*sizeof(TCHAR)
  1970. );
  1971. if (!pLinkElem)
  1972. {
  1973. *ppAppln = NULL;
  1974. return S_FALSE;
  1975. }
  1976. *ppAppln = static_cast<CAppln *>(pLinkElem);
  1977. return S_OK;
  1978. }
  1979. /*===================================================================
  1980. CApplnMgr::AddEngine
  1981. When a change notification occurs for a file being debugged,
  1982. we need to delete its associated scripting engine. The naive
  1983. approach of Releasing the engine during notification won't work
  1984. because the engine is on the wrong thread. Instead of marshaling
  1985. to the thread (which raises possibilities of deadlock or starving
  1986. the notification thread if debugging is happening on the debug
  1987. thread), the engines are added to a queue in the application.
  1988. When a request is serviced for debugging (which is now in the
  1989. correct thread context), the application object first flushes
  1990. this list by releasing the engines
  1991. ===================================================================*/
  1992. HRESULT CApplnMgr::AddEngine(CActiveScriptEngine *pEngine)
  1993. {
  1994. CScriptEngineCleanupElem *pScriptElem = new CScriptEngineCleanupElem(pEngine);
  1995. if (pScriptElem == NULL)
  1996. return E_OUTOFMEMORY;
  1997. pScriptElem->AppendTo(m_listEngineCleanup);
  1998. return S_OK;
  1999. }
  2000. /*===================================================================
  2001. CApplnMgr::CleanupEngines()
  2002. Call Release all engine cleanup list.
  2003. ===================================================================*/
  2004. void CApplnMgr::CleanupEngines()
  2005. {
  2006. while (! m_listEngineCleanup.FIsEmpty())
  2007. delete m_listEngineCleanup.PNext();
  2008. }
  2009. /*===================================================================
  2010. CApplnMgr::DeleteApplicationIfExpired
  2011. Removes CAppln object if exprired
  2012. Critical sectioning must be done outside
  2013. Parameters:
  2014. CAppln *pAppln application to delete
  2015. Returns:
  2016. NONE
  2017. ===================================================================*/
  2018. HRESULT CApplnMgr::DeleteApplicationIfExpired
  2019. (
  2020. CAppln *pAppln
  2021. )
  2022. {
  2023. if (!pAppln->m_fGlobalChanged)
  2024. return S_OK;
  2025. if (pAppln->m_cSessions || pAppln->m_cRequests)
  2026. return S_OK;
  2027. if (pAppln->m_fDeleteInProgress)
  2028. return S_OK;
  2029. pAppln->m_fDeleteInProgress = TRUE;
  2030. HRESULT hr = S_OK;
  2031. // Queue it up for deletion
  2032. CHitObj *pHitObj = new CHitObj;
  2033. if (!pHitObj)
  2034. hr = E_OUTOFMEMORY;
  2035. if (SUCCEEDED(hr))
  2036. {
  2037. pHitObj->ApplicationCleanupInit(pAppln);
  2038. // Ask Viper to queue this request
  2039. hr = pHitObj->PostViperAsyncCall();
  2040. }
  2041. // cleanup
  2042. if (FAILED(hr) && pHitObj)
  2043. delete pHitObj;
  2044. return hr;
  2045. }
  2046. /*===================================================================
  2047. CApplnMgr::DeleteAllApplications
  2048. Removes CAppln objects from the application manager link list
  2049. and hash table.
  2050. Parameters:
  2051. Returns:
  2052. HRESULT
  2053. ===================================================================*/
  2054. HRESULT CApplnMgr::DeleteAllApplications()
  2055. {
  2056. HRESULT hr = S_OK;
  2057. Lock();
  2058. CLinkElem *pLink = CHashTable::Head();
  2059. CHashTable::ReInit();
  2060. while (pLink)
  2061. {
  2062. CAppln *pAppln = static_cast<CAppln *>(pLink);
  2063. pLink = pLink->m_pNext;
  2064. if (pAppln->m_fDeleteInProgress)
  2065. continue;
  2066. pAppln->m_fDeleteInProgress = TRUE;
  2067. // Queue it up for deletion
  2068. CHitObj *pHitObj = new CHitObj;
  2069. if (!pHitObj)
  2070. {
  2071. hr = E_OUTOFMEMORY;
  2072. break;
  2073. }
  2074. // If NT, Unregister for notifications
  2075. if (FIsWinNT())
  2076. {
  2077. while ((pAppln->m_rgpvDME).Count())
  2078. {
  2079. static_cast<CDirMonitorEntry *>(pAppln->m_rgpvDME[0])->Release();
  2080. (pAppln->m_rgpvDME).Remove(0);
  2081. }
  2082. pAppln->m_rgpvDME.Clear();
  2083. }
  2084. pHitObj->ApplicationCleanupInit(pAppln);
  2085. // Ask Viper to queue this request
  2086. hr = pHitObj->PostViperAsyncCall();
  2087. if (FAILED(hr))
  2088. {
  2089. delete pHitObj;
  2090. break;
  2091. }
  2092. }
  2093. UnLock();
  2094. return hr;
  2095. }
  2096. /*===================================================================
  2097. CApplnMgr::RestartAllChagnedApplications
  2098. Restarts CAppln objects from the application manager link list
  2099. We walk the list recording which applications are dependent
  2100. on files that have changed since they were compiled. Once we
  2101. have the list, we restart each of the applications.
  2102. This is a fall back when we may have missed a change notification,
  2103. for instance when we had insufficient buffer to record all the changes
  2104. that occured.
  2105. Parameters:
  2106. Returns:
  2107. HRESULT
  2108. ===================================================================*/
  2109. HRESULT CApplnMgr::RestartApplications(BOOL fRestartAllApplications)
  2110. {
  2111. HRESULT hr = S_OK;
  2112. Lock();
  2113. CLinkElem *pLink = CHashTable::Head();
  2114. // Find out which applications need restarting
  2115. while (pLink)
  2116. {
  2117. CAppln *pAppln = static_cast<CAppln *>(pLink);
  2118. pLink = pLink->m_pNext;
  2119. if (!pAppln->FTombstone() && (fRestartAllApplications || (pAppln->m_pGlobalTemplate != NULL && pAppln->m_pGlobalTemplate->FTemplateObsolete())))
  2120. {
  2121. pAppln->Restart();
  2122. }
  2123. }
  2124. UnLock();
  2125. return hr;
  2126. }
  2127. /*===================================================================
  2128. C A p p l n C l e a n u p M g r
  2129. ===================================================================*/
  2130. /*===================================================================
  2131. CApplnMgr::CApplnCleanupMgr
  2132. Application Cleanup Manager constructor.
  2133. Parameters:
  2134. NONE
  2135. Returns:
  2136. NONE
  2137. ===================================================================*/
  2138. CApplnCleanupMgr::CApplnCleanupMgr()
  2139. : m_fInited(FALSE),
  2140. m_fCriticalSectionInited(FALSE),
  2141. m_fThreadAlive(FALSE),
  2142. m_hAppToCleanup(INVALID_HANDLE_VALUE)
  2143. {
  2144. m_List.m_pPrev = &m_List;
  2145. m_List.m_pNext = &m_List;
  2146. }
  2147. /*===================================================================
  2148. CApplnCleanupMgr::~CApplnCleanupMgr
  2149. Application Cleanup Manager destructor.
  2150. Parameters:
  2151. NONE
  2152. Returns:
  2153. NONE
  2154. ===================================================================*/
  2155. CApplnCleanupMgr::~CApplnCleanupMgr()
  2156. {
  2157. UnInit();
  2158. }
  2159. /*===================================================================
  2160. HRESULT CApplnCleanupMgr::Init
  2161. Initializes the Appln Cleanup Manager.
  2162. Parameters:
  2163. NONE
  2164. Returns:
  2165. S_OK Success
  2166. E_FAIL Failure
  2167. E_OUTOFMEMORY Out of memory
  2168. ===================================================================*/
  2169. HRESULT CApplnCleanupMgr::Init( void )
  2170. {
  2171. HRESULT hr = S_OK;
  2172. Assert(!m_fInited);
  2173. // Create delete app event
  2174. m_hAppToCleanup = IIS_CREATE_EVENT(
  2175. "CApplnCleanupMgr::m_hAppToCleanup",
  2176. this,
  2177. FALSE,
  2178. FALSE
  2179. );
  2180. if (!m_hAppToCleanup)
  2181. return E_FAIL;
  2182. // Init critical section
  2183. ErrInitCriticalSection(&m_csLock, hr);
  2184. if (FAILED(hr))
  2185. return(hr);
  2186. m_fCriticalSectionInited = TRUE;
  2187. HANDLE hThread = CreateThread(NULL, 0, CApplnCleanupMgr::ApplnCleanupThread, 0, 0, NULL);
  2188. if (!hThread) {
  2189. return E_FAIL;
  2190. }
  2191. CloseHandle(hThread);
  2192. m_fInited = TRUE;
  2193. return S_OK;
  2194. }
  2195. /*===================================================================
  2196. HRESULT CApplnCleanupMgr::UnInit
  2197. UnInitializes the Appln Cleanup Manager.
  2198. Parameters:
  2199. NONE
  2200. Returns:
  2201. S_OK Success
  2202. E_FAIL Failure
  2203. ===================================================================*/
  2204. HRESULT CApplnCleanupMgr::UnInit( void )
  2205. {
  2206. // set fInited to FALSE here so that the cleanup thread
  2207. // can safely detect that we're shutting down.
  2208. m_fInited = FALSE;
  2209. if (m_hAppToCleanup != INVALID_HANDLE_VALUE) {
  2210. // Set the event one last time so that the thread
  2211. // wakes up, sees that shutdown is occurring and
  2212. // exits.
  2213. SetEvent(m_hAppToCleanup);
  2214. CloseHandle(m_hAppToCleanup);
  2215. m_hAppToCleanup = INVALID_HANDLE_VALUE;
  2216. }
  2217. // we'll wait for the thread to finish its work
  2218. while(m_fThreadAlive) {
  2219. Sleep(200);
  2220. }
  2221. if (m_fCriticalSectionInited) {
  2222. DeleteCriticalSection(&m_csLock);
  2223. m_fCriticalSectionInited = FALSE;
  2224. }
  2225. return S_OK;
  2226. }
  2227. /*===================================================================
  2228. CApplnCleanupMgr::AddAppln
  2229. Adds a CAppln element to link list / hash table.
  2230. Parameters:
  2231. CAppln *pAppln Application to cleanup
  2232. Returns:
  2233. HRESULT
  2234. ===================================================================*/
  2235. HRESULT CApplnCleanupMgr::AddAppln
  2236. (
  2237. CAppln *pAppln
  2238. )
  2239. {
  2240. HRESULT hr = S_OK;
  2241. #if UNICODE
  2242. DBGPRINTF((DBG_CONTEXT, "[CApplnCleanupMgr] Adding App (%S)\n",pAppln->GetApplnPath(SOURCEPATHTYPE_VIRTUAL)));
  2243. #else
  2244. DBGPRINTF((DBG_CONTEXT, "[CApplnCleanupMgr] Adding App (%s)\n",pAppln->GetApplnPath(SOURCEPATHTYPE_VIRTUAL)));
  2245. #endif
  2246. Lock();
  2247. AddElem(pAppln);
  2248. UnLock();
  2249. if (SUCCEEDED(hr)) {
  2250. Wakeup();
  2251. }
  2252. return hr;
  2253. }
  2254. /*===================================================================
  2255. CApplnCleanupMgr::ApplnCleanupThread
  2256. The thread that does the work to cleanup applications
  2257. Parameters:
  2258. Returns:
  2259. HRESULT
  2260. ===================================================================*/
  2261. DWORD __stdcall CApplnCleanupMgr::ApplnCleanupThread(VOID *pArg)
  2262. {
  2263. g_ApplnCleanupMgr.ApplnCleanupDoWork();
  2264. return 0;
  2265. }
  2266. /*===================================================================
  2267. CApplnCleanupMgr::ApplnCleanupDoWork
  2268. Proc that actually does the work
  2269. Parameters:
  2270. Returns:
  2271. HRESULT
  2272. ===================================================================*/
  2273. void CApplnCleanupMgr::ApplnCleanupDoWork()
  2274. {
  2275. m_fThreadAlive = TRUE;
  2276. // this thread will be in a constant loop checking for work
  2277. while(1) {
  2278. // hold the lock while in this loop. This shouldn't hold it
  2279. // for long as there are no long running operations in this loop.
  2280. // If a thread can't be created and the application cleanup
  2281. // must occur on this thread, then the lock is released.
  2282. Lock();
  2283. // This loop will execute while there is work and there aren't too many
  2284. // threads active or we're in shutdown. The theory here is that in the
  2285. // non-shutdown case, let's not spin up more than 4 threads at a time to
  2286. // do the cleanup. If in shutdown, create as many threads as necessary.
  2287. while(Head() && ((g_nAppRestartThreads < 4) || (IsShutDownInProgress()))) {
  2288. CAppln *pAppln = static_cast<CAppln *>(Head());
  2289. RemoveElem(Head());
  2290. #if UNICODE
  2291. DBGPRINTF((DBG_CONTEXT, "[CApplnCleanupMgr] Cleanup Thread working on (%S)\n",pAppln->GetApplnPath(SOURCEPATHTYPE_VIRTUAL)));
  2292. #else
  2293. DBGPRINTF((DBG_CONTEXT, "[CApplnCleanupMgr] Cleanup Thread working on (%s)\n",pAppln->GetApplnPath(SOURCEPATHTYPE_VIRTUAL)));
  2294. #endif
  2295. HANDLE hThread = CreateThread(NULL, 0, CAppln::ApplnCleanupProc, pAppln, 0, NULL);
  2296. // failed to create a thread to do the work. Cleanup the app right here.
  2297. // Unlock the cleanup manager while we are doing this.
  2298. if (hThread == NULL) {
  2299. UnLock();
  2300. pAppln->ApplnCleanupProc(this);
  2301. Lock();
  2302. }
  2303. else {
  2304. InterlockedIncrement(&g_nAppRestartThreads);
  2305. CloseHandle(hThread);
  2306. }
  2307. }
  2308. UnLock();
  2309. WaitForSingleObject(m_hAppToCleanup, INFINITE);
  2310. // check the work queue under lock here to prevent the
  2311. // 'if' condition below from kicking in and preventing
  2312. // the remaining cleanup during shutdown
  2313. Lock();
  2314. if (Head()) {
  2315. UnLock();
  2316. continue;
  2317. }
  2318. UnLock();
  2319. // check to see if shutdown is occurring...
  2320. if (m_fInited == FALSE) {
  2321. Assert(Head() == NULL);
  2322. m_fThreadAlive = FALSE;
  2323. return;
  2324. }
  2325. }
  2326. return;
  2327. }
  2328. #define WSTR_NULL L"\0"
  2329. /*===================================================================
  2330. C A p p l n I t e r a t o r
  2331. ===================================================================*/
  2332. /*===================================================================
  2333. CApplnIterator::CApplnIterator
  2334. Constructor
  2335. Parameters:
  2336. NONE
  2337. Returns:
  2338. NONE
  2339. ===================================================================*/
  2340. CApplnIterator::CApplnIterator()
  2341. : m_pApplnMgr(NULL), m_pCurr(NULL), m_fEnded(FALSE)
  2342. {
  2343. }
  2344. /*===================================================================
  2345. CApplnIterator::~CApplnIterator
  2346. Destructor.
  2347. Parameters:
  2348. NONE
  2349. Returns:
  2350. NONE
  2351. ===================================================================*/
  2352. CApplnIterator::~CApplnIterator( void )
  2353. {
  2354. if (m_pApplnMgr != NULL)
  2355. Stop();
  2356. }
  2357. /*===================================================================
  2358. HRESULT CApplnIterator::Start
  2359. Starts iterator on the Appln Manager.
  2360. Parameters:
  2361. CApplnMgr * pApplnMgr Appln Manager
  2362. (if NULL g_ApplnManager is assumed)
  2363. Returns:
  2364. S_OK Success
  2365. E_FAIL Failure
  2366. ===================================================================*/
  2367. HRESULT CApplnIterator::Start
  2368. (
  2369. CApplnMgr *pApplnMgr
  2370. )
  2371. {
  2372. m_pApplnMgr = pApplnMgr ? m_pApplnMgr : &g_ApplnMgr;
  2373. m_pApplnMgr->Lock();
  2374. m_pCurr = NULL;
  2375. m_fEnded = FALSE;
  2376. return S_OK;
  2377. }
  2378. /*===================================================================
  2379. HRESULT CApplnIterator::Stop
  2380. Stops iterator on the Appln Manager.
  2381. Parameters:
  2382. NONE
  2383. Returns:
  2384. S_OK Success
  2385. E_FAIL Failure
  2386. ===================================================================*/
  2387. HRESULT CApplnIterator::Stop()
  2388. {
  2389. if (m_pApplnMgr)
  2390. {
  2391. m_pApplnMgr->UnLock();
  2392. m_pApplnMgr = NULL;
  2393. }
  2394. m_pCurr = NULL;
  2395. m_fEnded = FALSE;
  2396. return S_OK;
  2397. }
  2398. /*===================================================================
  2399. HRESULT CApplnIterator::Next
  2400. Iterates to the next Appln.
  2401. Parameters:
  2402. NONE
  2403. Returns:
  2404. Appln * or NULL
  2405. ===================================================================*/
  2406. CAppln *CApplnIterator::Next( void )
  2407. {
  2408. if (m_pApplnMgr == NULL || m_fEnded)
  2409. return NULL; // didn't start or already ended
  2410. CLinkElem *pT = m_pCurr ? m_pCurr->m_pNext : m_pApplnMgr->Head();
  2411. if (pT)
  2412. {
  2413. m_pCurr = static_cast<CAppln *>(pT);
  2414. return m_pCurr;
  2415. }
  2416. m_fEnded = TRUE;
  2417. return NULL;
  2418. }