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.

533 lines
10 KiB

  1. /*++
  2. Copyright (C) Microsoft Corporation, 1996 - 1999
  3. Module Name:
  4. handles
  5. Abstract:
  6. This header file describes the handle management service.
  7. Author:
  8. Doug Barlow (dbarlow) 5/9/1996
  9. Environment:
  10. Win32, C++ w/ Exceptions
  11. Notes:
  12. ?Notes?
  13. --*/
  14. #ifndef _HANDLES_H_
  15. #define _HANDLES_H_
  16. #ifndef HANDLE_TYPE
  17. #define HANDLE_TYPE DWORD_PTR
  18. #endif
  19. #if defined(_WIN64) || defined(WIN64)
  20. static const DWORD_PTR
  21. HANDLE_INDEX_MASK = 0x000000007fffffff,
  22. HANDLE_COUNT_MASK = 0x00ffffff00000000,
  23. HANDLE_ID_MASK = 0xff00000000000000;
  24. static const DWORD
  25. HANDLE_INDEX_OFFSET = 0,
  26. HANDLE_COUNT_OFFSET = 32,
  27. HANDLE_ID_OFFSET = 56;
  28. #elif defined(_WIN32) || defined(WIN32)
  29. static const DWORD_PTR
  30. HANDLE_INDEX_MASK = 0x0000ffff,
  31. HANDLE_COUNT_MASK = 0x00ff0000,
  32. HANDLE_ID_MASK = 0xff000000;
  33. static const DWORD
  34. HANDLE_INDEX_OFFSET = 0,
  35. HANDLE_COUNT_OFFSET = 16,
  36. HANDLE_ID_OFFSET = 24;
  37. #else
  38. #error "Unsupported handle type length"
  39. #endif
  40. class CHandleList;
  41. //
  42. //==============================================================================
  43. //
  44. // CCritSect
  45. //
  46. class CCritSect
  47. {
  48. public:
  49. CCritSect(LPCRITICAL_SECTION pCritSect)
  50. {
  51. m_pCritSect = pCritSect;
  52. EnterCriticalSection(m_pCritSect);
  53. };
  54. ~CCritSect()
  55. {
  56. LeaveCriticalSection(m_pCritSect);
  57. };
  58. protected:
  59. LPCRITICAL_SECTION m_pCritSect;
  60. };
  61. //
  62. //==============================================================================
  63. //
  64. // CHandle
  65. //
  66. class CHandle
  67. {
  68. protected:
  69. // Constructors & Destructor
  70. CHandle()
  71. {
  72. m_dwCount = 0;
  73. m_dwIndex = (DWORD)(HANDLE_INDEX_MASK >> HANDLE_INDEX_OFFSET);
  74. };
  75. virtual ~CHandle() { /* Mandatory Base Class Destructor */ };
  76. // Properties
  77. DWORD m_dwCount;
  78. DWORD m_dwIndex;
  79. // Methods
  80. friend class CHandleList;
  81. };
  82. //
  83. //==============================================================================
  84. //
  85. // CHandleList
  86. //
  87. class CHandleList
  88. {
  89. public:
  90. // Constructors & Destructor
  91. CHandleList(DWORD dwHandleId)
  92. {
  93. m_dwId = dwHandleId;
  94. m_Max = m_Mac = 0;
  95. m_phList = NULL;
  96. InitializeCriticalSection(&m_critSect);
  97. };
  98. virtual ~CHandleList()
  99. {
  100. Clear();
  101. DeleteCriticalSection(&m_critSect);
  102. };
  103. // Properties
  104. // Methods
  105. DWORD Count(void)
  106. {
  107. CCritSect csLock(&m_critSect);
  108. return m_Mac;
  109. };
  110. void
  111. Clear(void)
  112. {
  113. CCritSect csLock(&m_critSect);
  114. if (NULL != m_phList)
  115. {
  116. for (DWORD index = 0; index < m_Mac; index += 1)
  117. if (NULL != m_phList[index].phObject)
  118. delete m_phList[index].phObject;
  119. delete[] m_phList;
  120. m_phList = NULL;
  121. m_Max = 0;
  122. m_Mac = 0;
  123. }
  124. };
  125. CHandle *
  126. Close(
  127. IN HANDLE_TYPE hItem);
  128. HANDLE_TYPE
  129. Add(
  130. IN CHandle *phItem);
  131. CHandle * const
  132. GetQuietly(
  133. IN HANDLE_TYPE hItem);
  134. CHandle * const
  135. Get(
  136. IN HANDLE_TYPE hItem);
  137. HANDLE_TYPE
  138. IndexHandle(
  139. DWORD nItem);
  140. // Operators
  141. CHandle * const
  142. operator[](HANDLE_TYPE hItem)
  143. { return Get(hItem); };
  144. protected:
  145. struct HandlePtr
  146. {
  147. CHandle *phObject;
  148. DWORD dwCount;
  149. };
  150. // Properties
  151. DWORD
  152. m_dwId; // Id number of handle list.
  153. DWORD
  154. m_Max, // Number of element slots available.
  155. m_Mac; // Number of element slots used.
  156. HandlePtr *
  157. m_phList; // The elements.
  158. CRITICAL_SECTION
  159. m_critSect; // Handle list access control.
  160. // Methods
  161. HandlePtr *
  162. GetHandlePtr(
  163. IN HANDLE_TYPE hItem)
  164. const;
  165. };
  166. /*++
  167. Close:
  168. This routine closes an item in the handle array.
  169. Arguments:
  170. hItem - Supplies the handle to the object to be closed.
  171. Throws:
  172. ERROR_INVALID_HANDLE - The supplied handle value is invalid.
  173. Return Value:
  174. The referenced object.
  175. Author:
  176. Doug Barlow (dbarlow) 7/13/1995
  177. --*/
  178. inline CHandle *
  179. CHandleList::Close(
  180. IN HANDLE_TYPE hItem)
  181. {
  182. CHandle *phItem;
  183. CCritSect csLock(&m_critSect);
  184. HandlePtr *pHandlePtr = GetHandlePtr(hItem);
  185. if (NULL == pHandlePtr)
  186. throw (DWORD)ERROR_INVALID_HANDLE;
  187. phItem = pHandlePtr->phObject;
  188. if (NULL == phItem)
  189. throw (DWORD)ERROR_INVALID_HANDLE;
  190. pHandlePtr->phObject = NULL;
  191. pHandlePtr->dwCount += 1;
  192. return phItem;
  193. }
  194. /*++
  195. Add:
  196. This method adds an item to the Handle list.
  197. Arguments:
  198. pvItem - Supplies the value to be added to the list.
  199. Return Value:
  200. The resultant handle of the Add operation.
  201. Author:
  202. Doug Barlow (dbarlow) 10/10/1995
  203. --*/
  204. inline HANDLE_TYPE
  205. CHandleList::Add(
  206. IN CHandle *phItem)
  207. {
  208. DWORD index;
  209. HandlePtr * pHndl = NULL;
  210. //
  211. // Look for a vacant handle slot. We look through m_Max instead of m_Mac,
  212. // so that if all the official ones are used, we fall into unused territory.
  213. //
  214. CCritSect csLock(&m_critSect);
  215. for (index = 0; index < m_Max; index += 1)
  216. {
  217. pHndl = &m_phList[index];
  218. if (NULL == pHndl->phObject)
  219. break;
  220. pHndl = NULL;
  221. }
  222. //
  223. // Make sure the array was big enough.
  224. //
  225. if (NULL == pHndl)
  226. {
  227. DWORD newSize = (0 == m_Max ? 4 : m_Max * 2);
  228. if ((HANDLE_INDEX_MASK >> HANDLE_INDEX_OFFSET) < newSize)
  229. throw (DWORD)ERROR_OUTOFMEMORY;
  230. pHndl = new HandlePtr[newSize];
  231. if (NULL == pHndl)
  232. throw (DWORD)ERROR_OUTOFMEMORY;
  233. if (NULL != m_phList)
  234. {
  235. CopyMemory(pHndl, m_phList, sizeof(HandlePtr) * m_Mac);
  236. delete[] m_phList;
  237. }
  238. ZeroMemory(&pHndl[m_Mac], sizeof(HandlePtr) * (newSize - m_Mac));
  239. m_phList = pHndl;
  240. m_Max = (DWORD)newSize;
  241. index = m_Mac++;
  242. pHndl = &m_phList[index];
  243. }
  244. else
  245. {
  246. if (m_Mac <= index)
  247. m_Mac = index + 1;
  248. }
  249. //
  250. // Cross index the list element and the object.
  251. //
  252. ASSERT(NULL == pHndl->phObject);
  253. pHndl->phObject = phItem;
  254. if (0 == pHndl->dwCount)
  255. pHndl->dwCount = 1;
  256. phItem->m_dwCount = (DWORD)(pHndl->dwCount
  257. & (HANDLE_COUNT_MASK >> HANDLE_COUNT_OFFSET));
  258. phItem->m_dwIndex = index;
  259. return (HANDLE_TYPE)(
  260. ((((HANDLE_TYPE)m_dwId) << HANDLE_ID_OFFSET) & HANDLE_ID_MASK)
  261. | ((((HANDLE_TYPE)pHndl->dwCount) << HANDLE_COUNT_OFFSET) & HANDLE_COUNT_MASK)
  262. | ((((HANDLE_TYPE)index) << HANDLE_INDEX_OFFSET) & HANDLE_INDEX_MASK));
  263. }
  264. /*++
  265. GetQuietly:
  266. This method returns the element at the given handle. If the handle is
  267. invalid, it returns NULL. It does not expand the array.
  268. Arguments:
  269. hItem - Supplies the index into the list.
  270. Return Value:
  271. The value stored at that handle in the list, or NULL if the handle is
  272. invalid.
  273. Author:
  274. Doug Barlow (dbarlow) 7/13/1995
  275. --*/
  276. inline CHandle * const
  277. CHandleList::GetQuietly(
  278. HANDLE_TYPE hItem)
  279. {
  280. CCritSect csLock(&m_critSect);
  281. HandlePtr *pHandlePtr = GetHandlePtr(hItem);
  282. if (NULL == pHandlePtr)
  283. return NULL;
  284. return pHandlePtr->phObject;
  285. }
  286. /*++
  287. Get:
  288. This method returns the element at the given handle. If the handle is
  289. invalid, it throws an error. It does not expand the array.
  290. Arguments:
  291. hItem - Supplies the index into the list.
  292. Return Value:
  293. The value stored at that handle in the list.
  294. Throws:
  295. ERROR_INVALID_HANDLE - Invalid handle value.
  296. Author:
  297. Doug Barlow (dbarlow) 7/13/1995
  298. --*/
  299. inline CHandle * const
  300. CHandleList::Get(
  301. HANDLE_TYPE hItem)
  302. {
  303. CCritSect csLock(&m_critSect);
  304. HandlePtr *pHandlePtr = GetHandlePtr(hItem);
  305. if (NULL == pHandlePtr)
  306. throw (DWORD)ERROR_INVALID_HANDLE;
  307. return pHandlePtr->phObject;
  308. }
  309. /*++
  310. GetHandlePtr:
  311. This routine finds the HandlePtr structure corresponding to a given handle.
  312. Arguments:
  313. hItem supplies the handle to look up.
  314. Return Value:
  315. The address of the HandlePtr structure corresponding to the handle, or NULL
  316. if none exists.
  317. Author:
  318. Doug Barlow (dbarlow) 5/9/1996
  319. --*/
  320. inline CHandleList::HandlePtr *
  321. CHandleList::GetHandlePtr(
  322. HANDLE_TYPE hItem)
  323. const
  324. {
  325. try
  326. {
  327. HandlePtr *pHandlePtr;
  328. DWORD_PTR dwItem = (DWORD_PTR)hItem;
  329. DWORD dwId = (DWORD)((dwItem & HANDLE_ID_MASK) >> HANDLE_ID_OFFSET);
  330. DWORD dwCount = (DWORD)((dwItem & HANDLE_COUNT_MASK) >> HANDLE_COUNT_OFFSET);
  331. DWORD dwIndex = (DWORD)((dwItem & HANDLE_INDEX_MASK) >> HANDLE_INDEX_OFFSET);
  332. if (dwId != (m_dwId & (HANDLE_ID_MASK >> HANDLE_ID_OFFSET))
  333. || (m_Mac <= dwIndex))
  334. return NULL;
  335. pHandlePtr = &m_phList[dwIndex];
  336. if (dwCount
  337. != (pHandlePtr->dwCount
  338. & (HANDLE_ID_MASK >> HANDLE_ID_OFFSET)))
  339. return NULL;
  340. return pHandlePtr;
  341. }
  342. catch (...)
  343. {
  344. // Swallow the error.
  345. }
  346. return NULL;
  347. }
  348. /*++
  349. IndexHandle:
  350. This method converts an index into a handle. The handle is NULL if there is
  351. no element stored at that index.
  352. Arguments:
  353. nItem supplies the index of the object to reference.
  354. Return Value:
  355. The handle of the object, or NULL if there is no object at that index.
  356. Throws:
  357. None
  358. Author:
  359. Doug Barlow (dbarlow) 1/3/1997
  360. --*/
  361. inline HANDLE_TYPE
  362. CHandleList::IndexHandle(
  363. DWORD nItem)
  364. {
  365. HANDLE_TYPE hItem = NULL;
  366. HandlePtr * pHndl;
  367. CCritSect csLock(&m_critSect);
  368. if (m_Mac > nItem)
  369. {
  370. pHndl = &m_phList[nItem];
  371. if (NULL != pHndl->phObject)
  372. {
  373. hItem =
  374. ((((HANDLE_TYPE)m_dwId) << HANDLE_ID_OFFSET) & HANDLE_ID_MASK)
  375. | ((((HANDLE_TYPE)pHndl->dwCount) << HANDLE_COUNT_OFFSET) & HANDLE_COUNT_MASK)
  376. | ((((HANDLE_TYPE)nItem) << HANDLE_INDEX_OFFSET) & HANDLE_INDEX_MASK);
  377. }
  378. }
  379. return hItem;
  380. }
  381. #endif // _HANDLES_H_