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.

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