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

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