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.

188 lines
4.5 KiB

  1. #ifndef _COOKIE_HXX_
  2. #define _COOKIE_HXX_
  3. #ifdef __cplusplus
  4. #ifdef unix
  5. #include "../download/packet.hxx"
  6. #endif /* unix */
  7. // CCookie<TYPE>
  8. // This is a template for implementing a typesafe cookie that will prevent
  9. // re-entrancy by the same thread. Eg. when a thread posts a dialog box it
  10. // can still receive messages and can reenter a msg handler that
  11. // put up the dialog if not protected. This is a case with us putting up
  12. // WinVerifyTrust dialogs from OnStopBinding in code download. We want to
  13. // serialize this across different code downloads on the same thread and
  14. // different dependent piece downloads within the same code download.
  15. // we also use this to serialize the setup phase making sure only one code
  16. // download per thread is in setup phase
  17. // Rules:
  18. // to enter either the setup phase or to verify trust of a component
  19. // you need to acquire the corresponding cookie in tls.
  20. // pcookie->Acquire()
  21. // returns S_Ok if you grabbed the cookie successfully
  22. // returns S_FALSE if cookie is busy. You must return from the
  23. // msg handler and then a packet will get posted to you
  24. // with (wParam = id passed in, lParam (fixed for cookie obj)
  25. // when you pCookie->Relinquish() the next client on line will be posted a pkt
  26. template<class TYPE>
  27. class CCookie
  28. {
  29. public:
  30. CCookie(DWORD msg);
  31. BOOL IsFree() const;
  32. BOOL IsOwner(TYPE id) const;
  33. HRESULT Acquire(TYPE id);
  34. HRESULT Relinquish(TYPE id);
  35. HRESULT JITAcquire();
  36. HRESULT JITRelinquish();
  37. HRESULT TickleWaitList();
  38. private:
  39. TYPE m_owner;
  40. CList<TYPE,TYPE> m_pWaitList; // linked list of waiting clients
  41. DWORD m_msg; // client that gets cookie
  42. // wParam is the id (TYPE)
  43. DWORD m_lParam;
  44. BOOL m_bJITAcquired;
  45. };
  46. /////////////////////////////////////////////////////////////////////////////
  47. // CCookie<TYPE> functions
  48. template<class TYPE>
  49. CCookie<TYPE>::CCookie(DWORD msg):m_owner(NULL),m_lParam(0)
  50. {
  51. m_msg = msg;
  52. m_pWaitList.RemoveAll();
  53. m_bJITAcquired = FALSE;
  54. }
  55. template<class TYPE>
  56. BOOL CCookie<TYPE>::IsOwner(TYPE id) const
  57. { return (id == m_owner); }
  58. template<class TYPE>
  59. BOOL CCookie<TYPE>::IsFree() const
  60. { return ((NULL == m_owner) && !m_bJITAcquired); }
  61. // pcookie->Acquire()
  62. // returns S_Ok if you grabbed the cookie successfully
  63. // returns S_FALSE if cookie is busy. You must return from the
  64. // msg handler and then a packet will get posted to you
  65. // with (wParam = id passed in, lParam (fixed for cookie obj)
  66. template<class TYPE>
  67. HRESULT CCookie<TYPE>::Acquire(TYPE id)
  68. {
  69. HRESULT hr = S_OK;
  70. Assert(id);
  71. if (m_bJITAcquired || ((m_owner != NULL) && (m_owner != id))) {
  72. // add iff not already in list
  73. if (m_pWaitList.Find(id) == NULL)
  74. m_pWaitList.AddTail(id);
  75. hr = S_FALSE;
  76. } else {
  77. m_owner = id; // assign cookie
  78. }
  79. return hr;
  80. }
  81. // pCookie->Relinquish(): free the cookie
  82. // and the next client on line will get the cookie and be posted a packet
  83. // with (wParam = id passed in, lParam (fixed for cookie obj)
  84. template<class TYPE>
  85. HRESULT CCookie<TYPE>::Relinquish(TYPE id)
  86. {
  87. HRESULT hr = S_OK;
  88. Assert(id);
  89. Assert(m_owner);
  90. Assert(m_owner == id);
  91. if ((m_owner == NULL) || (m_owner != id)) {
  92. return E_UNEXPECTED;
  93. }
  94. hr = TickleWaitList();
  95. Assert(SUCCEEDED(hr));
  96. return hr;
  97. }
  98. template<class TYPE>
  99. HRESULT CCookie<TYPE>::TickleWaitList()
  100. {
  101. HRESULT hr = S_OK;
  102. if (m_pWaitList.GetCount() > 0)
  103. m_owner = m_pWaitList.RemoveHead();
  104. else
  105. m_owner = NULL;
  106. // if m_owner, post message to this new owner
  107. if (m_owner) {
  108. CCDLPacket *pPkt= new CCDLPacket(m_msg, m_owner, (DWORD)m_lParam);
  109. if (pPkt) {
  110. hr = pPkt->Post();
  111. } else {
  112. hr = E_OUTOFMEMORY;
  113. }
  114. }
  115. Assert(SUCCEEDED(hr));
  116. return hr;
  117. }
  118. template<class TYPE>
  119. HRESULT CCookie<TYPE>::JITAcquire()
  120. {
  121. Assert(m_owner == NULL);
  122. m_bJITAcquired = TRUE;
  123. return S_OK;
  124. }
  125. template<class TYPE>
  126. HRESULT CCookie<TYPE>::JITRelinquish()
  127. {
  128. HRESULT hr = S_OK;
  129. Assert(m_owner == NULL);
  130. m_bJITAcquired = FALSE;
  131. hr = TickleWaitList();
  132. Assert(SUCCEEDED(hr));
  133. return hr;
  134. }
  135. #endif
  136. #endif