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.

697 lines
18 KiB

  1. /*===================================================================
  2. Microsoft Denali
  3. Microsoft Confidential.
  4. Copyright 1996 Microsoft Corporation. All Rights Reserved.
  5. Component: Session Manager
  6. File: Sessmgr.h
  7. Owner: PramodD
  8. This is the session manager header file.
  9. ===================================================================*/
  10. #ifndef SESSMGR_H
  11. #define SESSMGR_H
  12. #include "debug.h"
  13. #include "idhash.h"
  14. #include "idgener.h"
  15. #include "compcol.h"
  16. #include "request.h"
  17. #include "response.h"
  18. #include "server.h"
  19. #include "viperint.h"
  20. #include "ftm.h"
  21. #include "memcls.h"
  22. /*===================================================================
  23. #defines
  24. ===================================================================*/
  25. // Min/Max session timeout in minutes
  26. #define SESSION_TIMEOUT_MIN 1 // 1 minute
  27. #define SESSION_TIMEOUT_MAX 1440 // 1 day
  28. // Master hash table sizes
  29. #define SESSION_MASTERHASH_SIZE1_MAX 499
  30. #define SESSION_MASTERHASH_SIZE2_MAX 31
  31. #define SESSION_MASTERHASH_SIZE3_MAX 13
  32. // Timeout bucket hash tables sizes
  33. #define SESSION_TIMEOUTHASH_SIZE1_MAX 97
  34. #define SESSION_TIMEOUTHASH_SIZE2_MAX 29
  35. #define SESSION_TIMEOUTHASH_SIZE3_MAX 11
  36. // Min/Max # of timeout buckets (hash tables)
  37. #define SESSION_TIMEOUTBUCKETS_MIN 10
  38. #define SESSION_TIMEOUTBUCKETS_MAX 45
  39. // max value of GetTickCount()
  40. #define DWT_MAX 0xFFFFFFFF
  41. // session killer workitem default wait
  42. #define MSEC_ONE_MINUTE 60000 // 1 min
  43. #include "asptlb.h"
  44. /*===================================================================
  45. Forward declarations
  46. ===================================================================*/
  47. class CAppln;
  48. class CHitObj;
  49. class CSession;
  50. /*===================================================================
  51. C S e s s i o n V a r i a n t s
  52. ===================================================================*/
  53. class CSessionVariants : public IVariantDictionary
  54. {
  55. private:
  56. ULONG m_cRefs; // ref count
  57. CSession * m_pSession; // pointer to parent object
  58. CompType m_ctColType; // collection type
  59. CSupportErrorInfo m_ISupportErrImp; // implementation of ISupportErr
  60. HRESULT ObjectNameFromVariant(VARIANT &vKey, WCHAR **ppwszName,
  61. BOOL fVerify = FALSE);
  62. public:
  63. CSessionVariants();
  64. ~CSessionVariants();
  65. HRESULT Init(CSession *pSession, CompType ctColType);
  66. HRESULT UnInit();
  67. // The Big Three
  68. STDMETHODIMP QueryInterface(const GUID &, void **);
  69. STDMETHODIMP_(ULONG) AddRef();
  70. STDMETHODIMP_(ULONG) Release();
  71. // OLE Automation Interface
  72. STDMETHODIMP get_Item(VARIANT VarKey, VARIANT *pvar);
  73. STDMETHODIMP put_Item(VARIANT VarKey, VARIANT var);
  74. STDMETHODIMP putref_Item(VARIANT VarKey, VARIANT var);
  75. STDMETHODIMP get_Key(VARIANT VarKey, VARIANT *pvar);
  76. STDMETHODIMP get__NewEnum(IUnknown **ppEnumReturn);
  77. STDMETHODIMP get_Count(int *pcValues);
  78. STDMETHODIMP Remove(VARIANT VarKey);
  79. STDMETHODIMP RemoveAll();
  80. // Cache on per-class basis
  81. ACACHE_INCLASS_DEFINITIONS()
  82. };
  83. /*===================================================================
  84. C S e s s i o n I D
  85. ===================================================================*/
  86. struct CSessionId
  87. {
  88. DWORD m_dwId; // Session Id
  89. DWORD m_dwR1; // Session Id random element 1
  90. DWORD m_dwR2; // Session Id random element 2
  91. CSessionId(DWORD dwId = INVALID_ID, DWORD dwR1 = 0, DWORD dwR2 = 0);
  92. };
  93. inline CSessionId::CSessionId(DWORD dwId, DWORD dwR1, DWORD dwR2)
  94. {
  95. m_dwId = dwId;
  96. m_dwR1 = dwR1;
  97. m_dwR2 = dwR2;
  98. }
  99. /*===================================================================
  100. C S e s s i o n
  101. ===================================================================*/
  102. class CSession : public ISessionObjectImpl, public CFTMImplementation
  103. {
  104. friend class CSessionMgr;
  105. friend class CSessionVariants;
  106. private:
  107. //========= Misc flags
  108. DWORD m_fInited : 1; // Are we initialized?
  109. DWORD m_fLightWeight : 1; // Is in lightweight form?
  110. DWORD m_fOnStartFailed : 1; // Session_OnStart failed?
  111. DWORD m_fOnStartInvoked : 1; // Session_OnStart invoked?
  112. DWORD m_fOnEndPresent : 1; // Need to invoke Session_OnEnd ?
  113. DWORD m_fTimedOut : 1; // Session timed out?
  114. DWORD m_fStateAcquired : 1; // Any property set (!m_fCanDelete)?
  115. DWORD m_fCustomTimeout : 1; // Timeout different from standard?
  116. DWORD m_fAbandoned : 1; // Session abandoned?
  117. DWORD m_fTombstone : 1; // ASP is done with the session?
  118. DWORD m_fInTOBucket : 1; // Session in a timeout bucket?
  119. DWORD m_fSessCompCol : 1; // Component collection present?
  120. DWORD m_fSecureSession : 1; // Is the session used over a secure line?
  121. DWORD m_fCodePageSet : 1; // CodePage explicitly set?
  122. DWORD m_fLCIDSet : 1; // LCID explicitly set?
  123. //========= Pointers to related objects
  124. CAppln *m_pAppln; // Session's Application
  125. CHitObj *m_pHitObj; // Session's current HitObj
  126. //========= Session's dictionaries for presenting component collection
  127. CSessionVariants *m_pTaggedObjects;
  128. CSessionVariants *m_pProperties;
  129. //========= Session data
  130. CSessionId m_Id; // Session ID + 2 random keys
  131. DWORD m_dwExternId; // Session ID to be given out (Session.ID)
  132. DWORD m_cRefs; // Ref count
  133. DWORD m_cRequests; // Requests count
  134. // Timeout when current time (in minutes) reaches this
  135. // The timeout bucket is current_time mod #_of_buckets
  136. DWORD m_dwmTimeoutTime;
  137. long m_lCodePage; // Code page for this session
  138. LCID m_lcid; // LCID for this session
  139. long m_nTimeout; // Current time value in minutes
  140. // to make session elem in the timeout bucket
  141. CObjectListElem m_TOBucketElem;
  142. #ifndef PERF_DISABLE
  143. DWORD m_dwtInitTimestamp; // Timestamp of session creation for PERFMON
  144. #endif
  145. //========= Session's Component Collection
  146. // to avoid the memory fragmentation component collection is
  147. // aggregated here. its validity is indicated by m_fSessCompCol flag
  148. CComponentCollection m_SessCompCol; // Session scope objects
  149. //========= Viper Activity of this Session
  150. CViperActivity m_Activity;
  151. //========= Intrinsics for this Session
  152. CRequest m_Request;
  153. CResponse m_Response;
  154. CServer m_Server;
  155. //========= SupportErrorInfo
  156. // Interface to indicate that we support ErrorInfo reporting
  157. CSupportErrorInfo m_ISuppErrImp;
  158. public:
  159. CSession();
  160. ~CSession();
  161. HRESULT Init(CAppln *pAppln, const CSessionId &Id);
  162. // Convert to tombstone state
  163. HRESULT UnInit();
  164. // Convert to 'light-weight' state if possible
  165. HRESULT MakeLightWeight();
  166. // Create/Remove Session's component collection
  167. HRESULT CreateComponentCollection();
  168. HRESULT RemoveComponentCollection();
  169. // Check if the session should be deleted
  170. BOOL FShouldBeDeletedNow(BOOL fAtEndOfRequest);
  171. // Non-delegating object IUnknown
  172. STDMETHODIMP QueryInterface(REFIID, void **);
  173. STDMETHODIMP_(ULONG) AddRef();
  174. STDMETHODIMP_(ULONG) Release();
  175. // Tombstone stub
  176. HRESULT CheckForTombstone();
  177. // ISessionObject functions
  178. STDMETHODIMP get_SessionID(BSTR *pbstrRet);
  179. STDMETHODIMP get_Timeout(long *plVar);
  180. STDMETHODIMP put_Timeout(long lVar);
  181. STDMETHODIMP get_CodePage(long *plVar);
  182. STDMETHODIMP put_CodePage(long lVar);
  183. STDMETHODIMP get_Value(BSTR bstr, VARIANT FAR * pvar);
  184. STDMETHODIMP put_Value(BSTR bstr, VARIANT var);
  185. STDMETHODIMP putref_Value(BSTR bstr, VARIANT var);
  186. STDMETHODIMP Abandon();
  187. STDMETHODIMP get_LCID(long *plVar);
  188. STDMETHODIMP put_LCID(long lVar);
  189. STDMETHODIMP get_StaticObjects(IVariantDictionary **ppDictReturn);
  190. STDMETHODIMP get_Contents(IVariantDictionary **ppDictReturn);
  191. // inline methods to access member properties
  192. CAppln *PAppln();
  193. CHitObj *PHitObj();
  194. CComponentCollection *PCompCol();
  195. CViperActivity *PActivity();
  196. CRequest *PRequest();
  197. CResponse *PResponse();
  198. CServer *PServer();
  199. BOOL FCustomTimeout();
  200. BOOL FAbandoned();
  201. DWORD GetId();
  202. BOOL FInTOBucket();
  203. LCID GetLCID();
  204. long GetCodePage();
  205. DWORD GetTimeoutTime();
  206. BOOL FSecureSession();
  207. // inline methods to set member properties
  208. void SetHitObj(CHitObj *pHitObj);
  209. void SetOnStartFailedFlag();
  210. void SetOnStartInvokedFlag();
  211. void SetOnEndPresentFlag();
  212. HRESULT SetLCID(LCID lcid);
  213. // Misc inline methods
  214. DWORD IncrementRequestsCount();
  215. DWORD DecrementRequestsCount();
  216. DWORD GetRequestsCount();
  217. BOOL FCanDeleteWithoutExec();
  218. BOOL FHasObjects();
  219. BOOL FPassesIdSecurityCheck(DWORD dwR1, DWORD dwR2);
  220. void AssignNewId(const CSessionId &Id);
  221. void SetSecureSession(BOOL fSecure);
  222. BOOL FCodePageSet();
  223. BOOL FLCIDSet();
  224. // AssertValid()
  225. public:
  226. #ifdef DBG
  227. virtual void AssertValid() const;
  228. #else
  229. virtual void AssertValid() const {}
  230. #endif
  231. // Cache on per-class basis
  232. ACACHE_INCLASS_DEFINITIONS()
  233. // Trace Log info -- keep in both free & checked builds so that ntsd extension will work for both builds
  234. // for FREE build, trace log is always NULL. Checked builds, it must be enabled.
  235. static PTRACE_LOG gm_pTraceLog;
  236. };
  237. /*===================================================================
  238. C S e s s i o n inlines
  239. ===================================================================*/
  240. inline CAppln *CSession::PAppln()
  241. {
  242. Assert(m_fInited);
  243. return m_pAppln;
  244. }
  245. inline CHitObj *CSession::PHitObj()
  246. {
  247. Assert(m_fInited);
  248. return m_pHitObj;
  249. }
  250. inline CComponentCollection *CSession::PCompCol()
  251. {
  252. Assert(m_fInited);
  253. return (m_fSessCompCol ? &m_SessCompCol : NULL);
  254. }
  255. inline CViperActivity *CSession::PActivity()
  256. {
  257. Assert(m_fInited);
  258. return &m_Activity;
  259. }
  260. inline CRequest *CSession::PRequest()
  261. {
  262. Assert(m_fInited);
  263. return &m_Request;
  264. }
  265. inline CResponse *CSession::PResponse()
  266. {
  267. Assert(m_fInited);
  268. return &m_Response;
  269. }
  270. inline CServer *CSession::PServer()
  271. {
  272. Assert(m_fInited);
  273. return &m_Server;
  274. }
  275. inline BOOL CSession::FCustomTimeout()
  276. {
  277. Assert(m_fInited);
  278. return m_fCustomTimeout;
  279. }
  280. inline BOOL CSession::FAbandoned()
  281. {
  282. Assert(m_fInited);
  283. return m_fAbandoned;
  284. }
  285. inline DWORD CSession::GetId()
  286. {
  287. Assert(m_fInited);
  288. return m_Id.m_dwId;
  289. }
  290. inline BOOL CSession::FInTOBucket()
  291. {
  292. Assert(m_fInited);
  293. return m_fInTOBucket;
  294. }
  295. inline LCID CSession::GetLCID()
  296. {
  297. Assert(m_fInited);
  298. return (UINT)m_lcid;
  299. }
  300. inline long CSession::GetCodePage()
  301. {
  302. Assert(m_fInited);
  303. return m_lCodePage;
  304. }
  305. inline BOOL CSession::FCodePageSet()
  306. {
  307. Assert(m_fInited);
  308. return (m_fCodePageSet);
  309. }
  310. inline BOOL CSession::FLCIDSet()
  311. {
  312. Assert(m_fInited);
  313. return (m_fLCIDSet);
  314. }
  315. inline DWORD CSession::GetTimeoutTime()
  316. {
  317. Assert(m_fInited);
  318. return m_dwmTimeoutTime;
  319. }
  320. inline BOOL CSession::FSecureSession()
  321. {
  322. Assert(m_fInited);
  323. return m_fSecureSession;
  324. }
  325. inline void CSession::SetHitObj(CHitObj *pHitObj)
  326. {
  327. Assert(m_fInited);
  328. Assert(pHitObj ? (m_pHitObj == NULL) : (m_pHitObj != NULL));
  329. m_pHitObj = pHitObj;
  330. }
  331. inline void CSession::SetOnStartFailedFlag()
  332. {
  333. Assert(m_fInited);
  334. m_fOnStartFailed = TRUE;
  335. }
  336. inline void CSession::SetOnStartInvokedFlag()
  337. {
  338. Assert(m_fInited);
  339. m_fOnStartInvoked = TRUE;
  340. }
  341. inline void CSession::SetOnEndPresentFlag()
  342. {
  343. Assert(m_fInited);
  344. m_fOnEndPresent = TRUE;
  345. }
  346. inline HRESULT CSession::SetLCID(LCID lcid)
  347. {
  348. Assert(m_fInited);
  349. if ((LOCALE_SYSTEM_DEFAULT == lcid) || IsValidLocale(lcid, LCID_INSTALLED))
  350. {
  351. m_lcid = lcid;
  352. return S_OK;
  353. }
  354. else
  355. {
  356. return E_FAIL;
  357. }
  358. }
  359. inline DWORD CSession::IncrementRequestsCount()
  360. {
  361. Assert(m_fInited);
  362. return InterlockedIncrement((LPLONG)&m_cRequests);
  363. }
  364. inline DWORD CSession::DecrementRequestsCount()
  365. {
  366. Assert(m_fInited);
  367. return InterlockedDecrement((LPLONG)&m_cRequests);
  368. }
  369. inline DWORD CSession::GetRequestsCount()
  370. {
  371. Assert(m_fInited);
  372. return m_cRequests;
  373. }
  374. inline BOOL CSession::FCanDeleteWithoutExec()
  375. {
  376. // Return TRUE to delete CSession right away or FALSE to
  377. // post Viper request to execute Session_OnEnd()
  378. return (m_fOnStartFailed || !m_fOnEndPresent);
  379. }
  380. inline BOOL CSession::FHasObjects()
  381. {
  382. return m_fSessCompCol && m_SessCompCol.FHasObjects();
  383. }
  384. inline BOOL CSession::FPassesIdSecurityCheck(DWORD dwR1, DWORD dwR2)
  385. {
  386. Assert(m_fInited);
  387. return (m_Id.m_dwR1 == dwR1 && m_Id.m_dwR2 == dwR2);
  388. }
  389. inline void CSession::AssignNewId(const CSessionId &Id)
  390. {
  391. Assert(m_fInited);
  392. m_Id = Id;
  393. }
  394. inline void CSession::SetSecureSession(BOOL fSecure)
  395. {
  396. Assert(m_fInited);
  397. m_fSecureSession = fSecure;
  398. }
  399. /*===================================================================
  400. C S e s s i o n M g r
  401. ===================================================================*/
  402. class CSessionMgr
  403. {
  404. private:
  405. // Flags
  406. DWORD m_fInited : 1; // Are we initialized?
  407. // Application
  408. CAppln *m_pAppln;
  409. // Sessions master hash table
  410. CIdHashTableWithLock m_htidMaster;
  411. // Number of posted Session Cleanup requests
  412. DWORD m_cSessionCleanupRequests;
  413. // Timeout buckets
  414. DWORD m_cTimeoutBuckets;
  415. CObjectListWithLock *m_rgolTOBuckets;
  416. // Session killer scheduler workitem
  417. DWORD m_idSessionKiller; // workitem id
  418. DWORD m_dwmCurrentTime; // current time in minutes since start
  419. DWORD m_dwtNextSessionKillerTime; // next session killer time
  420. public:
  421. CSessionMgr();
  422. ~CSessionMgr();
  423. // Init/Unit
  424. HRESULT Init(CAppln *pAppln);
  425. HRESULT UnInit();
  426. // Add/remove session killer workitem
  427. HRESULT ScheduleSessionKiller();
  428. HRESULT UnScheduleSessionKiller();
  429. BOOL FIsSessionKillerScheduled();
  430. // Lock/Unlock master hash table
  431. HRESULT LockMaster();
  432. HRESULT UnLockMaster();
  433. // Lock/Unlock a timeout bucket hash table
  434. HRESULT LockTOBucket(DWORD iBucket);
  435. HRESULT UnLockTOBucket(DWORD iBucket);
  436. // Get current time in minute ticks
  437. DWORD GetCurrentTime();
  438. // Set the time when the session should be gone
  439. HRESULT UpdateSessionTimeoutTime(CSession *pSession);
  440. // Calculate which timeout bucket the session's in
  441. DWORD GetSessionTOBucket(CSession *pSession);
  442. // Generate new ID and cookie
  443. HRESULT GenerateIdAndCookie(CSessionId *pId, char *pszCookie);
  444. // Create new session object
  445. HRESULT NewSession(const CSessionId &Id, CSession **ppSession);
  446. // Reassign session's Id (reinsert session into master hash)
  447. HRESULT ChangeSessionId(CSession *pSession, const CSessionId &Id);
  448. // Master hash table manipulations
  449. HRESULT AddToMasterHash(CSession *pSession);
  450. HRESULT RemoveFromMasterHash(CSession *pSession);
  451. HRESULT FindInMasterHash(const CSessionId &Id, CSession **ppSession);
  452. // Insert/remove session into the timeout bucket hash table
  453. HRESULT AddSessionToTOBucket(CSession *pSession);
  454. HRESULT RemoveSessionFromTOBucket(CSession *pSession, BOOL fLock = TRUE);
  455. // Delete session now or queue for deletion
  456. HRESULT DeleteSession(CSession *pSession, BOOL fInSessActivity = FALSE);
  457. // Delete expired sessions from a given bucket
  458. HRESULT DeleteExpiredSessions(DWORD iBucket);
  459. // Delete all sessions (application shut-down code)
  460. HRESULT DeleteAllSessions(BOOL fForce);
  461. // Static iterator call back to delete all sessions
  462. static IteratorCallbackCode DeleteAllSessionsCB(void *, void *, void *);
  463. // The Session Killer
  464. static VOID WINAPI SessionKillerSchedulerCallback(VOID *pv);
  465. // Incr/Decr/Get number of posted Session Cleanup requests
  466. void IncrementSessionCleanupRequestCount();
  467. void DecrementSessionCleanupRequestCount();
  468. DWORD GetNumSessionCleanupRequests();
  469. // AssertValid()
  470. public:
  471. #ifdef DBG
  472. virtual void AssertValid() const;
  473. #else
  474. virtual void AssertValid() const {}
  475. #endif
  476. };
  477. inline BOOL CSessionMgr::FIsSessionKillerScheduled()
  478. {
  479. return (m_idSessionKiller != 0);
  480. }
  481. inline HRESULT CSessionMgr::LockMaster()
  482. {
  483. m_htidMaster.Lock();
  484. return S_OK;
  485. }
  486. inline HRESULT CSessionMgr::UnLockMaster()
  487. {
  488. m_htidMaster.UnLock();
  489. return S_OK;
  490. }
  491. inline HRESULT CSessionMgr::LockTOBucket(DWORD iBucket)
  492. {
  493. Assert(m_rgolTOBuckets);
  494. Assert(iBucket < m_cTimeoutBuckets);
  495. m_rgolTOBuckets[iBucket].Lock();
  496. return S_OK;
  497. }
  498. inline HRESULT CSessionMgr::UnLockTOBucket(DWORD iBucket)
  499. {
  500. Assert(m_rgolTOBuckets);
  501. Assert(iBucket < m_cTimeoutBuckets);
  502. m_rgolTOBuckets[iBucket].UnLock();
  503. return S_OK;
  504. }
  505. inline DWORD CSessionMgr::GetCurrentTime()
  506. {
  507. return m_dwmCurrentTime;
  508. }
  509. inline HRESULT CSessionMgr::UpdateSessionTimeoutTime(CSession *pSession)
  510. {
  511. Assert(pSession);
  512. // remember when the session times out
  513. pSession->m_dwmTimeoutTime =
  514. m_dwmCurrentTime + pSession->m_nTimeout + 1;
  515. return S_OK;
  516. }
  517. inline DWORD CSessionMgr::GetSessionTOBucket(CSession *pSession)
  518. {
  519. Assert(pSession->m_fInited);
  520. return (pSession->m_dwmTimeoutTime % m_cTimeoutBuckets);
  521. }
  522. inline HRESULT CSessionMgr::AddToMasterHash(CSession *pSession)
  523. {
  524. Assert(m_fInited);
  525. return m_htidMaster.AddObject(pSession->GetId(), pSession);
  526. }
  527. inline HRESULT CSessionMgr::RemoveFromMasterHash(CSession *pSession)
  528. {
  529. Assert(m_fInited);
  530. return m_htidMaster.RemoveObject(pSession->GetId());
  531. }
  532. inline void CSessionMgr::IncrementSessionCleanupRequestCount()
  533. {
  534. InterlockedIncrement((LPLONG)&m_cSessionCleanupRequests);
  535. }
  536. inline void CSessionMgr::DecrementSessionCleanupRequestCount()
  537. {
  538. InterlockedDecrement((LPLONG)&m_cSessionCleanupRequests);
  539. }
  540. inline DWORD CSessionMgr::GetNumSessionCleanupRequests()
  541. {
  542. return m_cSessionCleanupRequests;
  543. }
  544. /*===================================================================
  545. G l o b a l s
  546. ===================================================================*/
  547. // There are multiple session managers (one per application)
  548. // The following variables are 1 per ASP.DLL
  549. extern unsigned long g_nSessions;
  550. extern CIdGenerator g_SessionIdGenerator;
  551. extern CIdGenerator g_ExposedSessionIdGenerator;
  552. #endif // SESSMGR_H