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.

322 lines
8.4 KiB

  1. /***************************************************************************\
  2. *
  3. * File: TicketManager.cpp
  4. *
  5. * Description:
  6. *
  7. * This file contains the implementation of relevant classes, structs, and
  8. * types for the DUser Ticket Manager.
  9. *
  10. * The following classes are defined for public use:
  11. *
  12. * DuTicketManager
  13. * A facility which can assign a unique "ticket" to a BaseObject.
  14. *
  15. * History:
  16. * 9/20/2000: DwayneN: Created
  17. *
  18. * Copyright (C) 2000 by Microsoft Corporation. All rights reserved.
  19. *
  20. \***************************************************************************/
  21. #include "stdafx.h"
  22. #include "Services.h"
  23. #include "TicketManager.h"
  24. #define INIT_OUT_PARAM(p,v) if(p != NULL) *p = v
  25. #define VALIDATE_REQUIRED_OUT_PARAM(p) if(p == NULL) return E_POINTER;
  26. #define VALIDATE_IN_PARAM_NOT_VALUE(p,v) if(p == v) return E_INVALIDARG;
  27. //------------------------------------------------------------------------------
  28. DuTicketManager::DuTicketManager()
  29. {
  30. Assert(sizeof(DuTicket) == sizeof(DWORD));
  31. m_idxFreeStackTop = -1;
  32. m_idxFreeStackBottom = -1;
  33. }
  34. //------------------------------------------------------------------------------
  35. DuTicketManager::~DuTicketManager()
  36. {
  37. }
  38. //------------------------------------------------------------------------------
  39. HRESULT
  40. DuTicketManager::Add(
  41. IN BaseObject * pObject,
  42. OUT DWORD * pdwTicket)
  43. {
  44. HRESULT hr = S_OK;
  45. int idxFree = 0;
  46. //
  47. // Parameter checking.
  48. // - Initialize all out parameters
  49. // - Validate in parameters
  50. //
  51. INIT_OUT_PARAM(pdwTicket, 0);
  52. VALIDATE_REQUIRED_OUT_PARAM(pdwTicket);
  53. VALIDATE_IN_PARAM_NOT_VALUE(pObject, NULL);
  54. m_crit.Enter();
  55. //
  56. // Scan to make sure the object isn't already in the array.
  57. // This is too expensive to do outside of DEBUG builds.
  58. //
  59. Assert(FAILED(Find(pObject, idxFree)));
  60. hr = PopFree(idxFree);
  61. if (SUCCEEDED(hr)) {
  62. DuTicket ticket;
  63. m_arTicketData[idxFree].pObject = pObject;
  64. ticket.Unused = 0;
  65. ticket.Uniqueness = m_arTicketData[idxFree].cUniqueness;
  66. ticket.Type = pObject->GetHandleType();
  67. ticket.Index = idxFree;
  68. *pdwTicket = DuTicket::CastToDWORD(ticket);
  69. }
  70. m_crit.Leave();
  71. return hr;
  72. }
  73. //------------------------------------------------------------------------------
  74. HRESULT
  75. DuTicketManager::Remove(
  76. IN DWORD dwTicket,
  77. OUT OPTIONAL BaseObject ** ppObject)
  78. {
  79. HRESULT hr = S_OK;
  80. //
  81. // Parameter checking.
  82. // - Initialize all out parameters
  83. // - Validate in parameters
  84. //
  85. INIT_OUT_PARAM(ppObject, NULL);
  86. VALIDATE_IN_PARAM_NOT_VALUE(dwTicket, 0);
  87. m_crit.Enter();
  88. hr = Lookup(dwTicket, ppObject);
  89. if (SUCCEEDED(hr)) {
  90. DuTicket ticket = DuTicket::CastFromDWORD(dwTicket);
  91. //
  92. // Clear out the object at this index just in case.
  93. //
  94. m_arTicketData[ticket.Index].pObject = NULL;
  95. //
  96. // Increment the uniqueness to invalidate any outstanding tickets.
  97. //
  98. m_arTicketData[ticket.Index].cUniqueness++;
  99. if (m_arTicketData[ticket.Index].cUniqueness == 0) {
  100. m_arTicketData[ticket.Index].cUniqueness = 1;
  101. }
  102. //
  103. // Push this index back onto the free stack.
  104. //
  105. PushFree(ticket.Index);
  106. }
  107. m_crit.Leave();
  108. return(hr);
  109. }
  110. //------------------------------------------------------------------------------
  111. HRESULT
  112. DuTicketManager::Lookup(
  113. IN DWORD dwTicket,
  114. OUT OPTIONAL BaseObject ** ppObject)
  115. {
  116. HRESULT hr = S_OK;
  117. DuTicket ticket = DuTicket::CastFromDWORD(dwTicket);
  118. //
  119. // Parameter checking.
  120. // - Initialize all out parameters
  121. // - Validate in parameters
  122. // - Check for manifest errors in the ticket
  123. //
  124. INIT_OUT_PARAM(ppObject, NULL);
  125. VALIDATE_IN_PARAM_NOT_VALUE(dwTicket, 0);
  126. if (ticket.Unused != 0 ||
  127. ticket.Uniqueness == 0 ||
  128. ticket.Index >= WORD(m_arTicketData.GetSize())) {
  129. return E_INVALIDARG;
  130. }
  131. m_crit.Enter();
  132. //
  133. // Look up the information in the tables and see if the
  134. // ticket still looks valid.
  135. //
  136. if (m_arTicketData[ticket.Index].cUniqueness == ticket.Uniqueness) {
  137. if (ppObject != NULL && m_arTicketData[ticket.Index].pObject != NULL) {
  138. if (ticket.Type == BYTE(m_arTicketData[ticket.Index].pObject->GetHandleType())) {
  139. *ppObject = m_arTicketData[ticket.Index].pObject;
  140. }
  141. }
  142. } else {
  143. //
  144. // It seems like the ticket has gone stale.
  145. //
  146. hr = DU_E_NOTFOUND;
  147. }
  148. m_crit.Leave();
  149. return hr;
  150. }
  151. //------------------------------------------------------------------------------
  152. HRESULT
  153. DuTicketManager::Expand()
  154. {
  155. //
  156. // We only need to resize our internal arrays when the free stack is empty.
  157. //
  158. Assert(m_idxFreeStackBottom == -1 && m_idxFreeStackTop == -1);
  159. //
  160. // Get the old size of the array, and calculate a new size.
  161. // Note that we limit how big the table can grow.
  162. //
  163. int cOldSize = m_arTicketData.GetSize();
  164. int cNewSize;
  165. if (cOldSize > 0) {
  166. if (cOldSize < USHRT_MAX) {
  167. cNewSize = min(cOldSize * 2, USHRT_MAX);
  168. } else {
  169. return E_OUTOFMEMORY;
  170. }
  171. } else {
  172. cNewSize = 16;
  173. }
  174. //
  175. // Resize the array of objects. The contents of the new items will
  176. // be set to NULL;
  177. //
  178. if (m_arTicketData.SetSize(cNewSize)) {
  179. //
  180. // Initialize the new data.
  181. //
  182. for (int i = cOldSize; i < cNewSize; i++) {
  183. m_arTicketData[i].pObject = NULL;
  184. m_arTicketData[i].cUniqueness = 1;
  185. m_arTicketData[i].idxFree = WORD(i);
  186. }
  187. m_idxFreeStackBottom = cOldSize;
  188. m_idxFreeStackTop = cNewSize - 1;
  189. } else {
  190. return E_OUTOFMEMORY;
  191. }
  192. return S_OK;
  193. }
  194. //------------------------------------------------------------------------------
  195. HRESULT
  196. DuTicketManager::PushFree(int idxFree)
  197. {
  198. if (m_idxFreeStackBottom == -1 && m_idxFreeStackTop == -1) {
  199. Assert(m_arTicketData.GetSize() > 0);
  200. m_idxFreeStackBottom = 0;
  201. m_idxFreeStackTop = 0;
  202. m_arTicketData[0].idxFree = WORD(idxFree);
  203. } else {
  204. int iNewTop = (m_idxFreeStackTop + 1) % m_arTicketData.GetSize();
  205. AssertMsg(iNewTop != m_idxFreeStackBottom, "Probably more pushes than pops!");
  206. m_arTicketData[iNewTop].idxFree = WORD(idxFree);
  207. m_idxFreeStackTop = iNewTop;
  208. }
  209. return S_OK;
  210. }
  211. //------------------------------------------------------------------------------
  212. HRESULT
  213. DuTicketManager::PopFree(int & idxFree)
  214. {
  215. HRESULT hr = S_OK;
  216. //
  217. // Resize our arrays if our stack of available slots is empty.
  218. //
  219. if (m_idxFreeStackBottom == -1 || m_idxFreeStackTop == -1) {
  220. hr = Expand();
  221. Assert(SUCCEEDED(hr));
  222. if (FAILED(hr)) {
  223. return hr;
  224. }
  225. }
  226. Assert(m_idxFreeStackBottom >=0 && m_idxFreeStackTop >=0 );
  227. //
  228. // Take the available slot from the bottom of the stack.
  229. //
  230. idxFree = m_arTicketData[m_idxFreeStackBottom].idxFree;
  231. //
  232. // Increment the bottom of the stack. If the stack is now empty,
  233. // indicate so by setting the top and bottom to -1.
  234. //
  235. if (m_idxFreeStackBottom == m_idxFreeStackTop) {
  236. m_idxFreeStackBottom = -1;
  237. m_idxFreeStackTop = -1;
  238. } else {
  239. m_idxFreeStackBottom = (m_idxFreeStackBottom + 1) % m_arTicketData.GetSize();
  240. }
  241. return S_OK;
  242. }
  243. //------------------------------------------------------------------------------
  244. HRESULT
  245. DuTicketManager::Find(BaseObject * pObject, int & iFound)
  246. {
  247. HRESULT hr = DU_E_NOTFOUND;
  248. iFound = -1;
  249. //
  250. // Note: This is a brute-force find. It does a linear search for the
  251. // specified pointer. This is very, very slow so don't use it unless
  252. // you absolutely have to. The BaseObject itself should remember what
  253. // its ticket is so it doesn't have to search.
  254. //
  255. for (int i = 0; i < m_arTicketData.GetSize(); i++) {
  256. if (m_arTicketData[i].pObject == pObject) {
  257. hr = S_OK;
  258. iFound = i;
  259. break;
  260. }
  261. }
  262. return hr;
  263. }