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.

624 lines
12 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. public:
  69. BOOL IsBad(void)
  70. { return m_fIsBad;};
  71. protected:
  72. // Constructors & Destructor
  73. CHandle()
  74. {
  75. m_dwCount = 0;
  76. m_dwIndex = (DWORD)(HANDLE_INDEX_MASK >> HANDLE_INDEX_OFFSET);
  77. m_fIsBad = FALSE;
  78. };
  79. virtual ~CHandle() { /* Mandatory Base Class Destructor */ };
  80. // Properties
  81. DWORD m_dwCount;
  82. DWORD m_dwIndex;
  83. BOOL m_fIsBad;
  84. // Methods
  85. virtual void Cancel(void) {};
  86. virtual void MarkAsBad(BOOL fCancel)
  87. {
  88. m_fIsBad = TRUE;
  89. if (fCancel)
  90. Cancel();
  91. };
  92. friend class CHandleList;
  93. };
  94. //
  95. //==============================================================================
  96. //
  97. // CHandleList
  98. //
  99. class CHandleList
  100. {
  101. public:
  102. // Constructors & Destructor
  103. CHandleList(DWORD dwHandleId)
  104. {
  105. m_dwId = dwHandleId;
  106. m_Max = m_Mac = 0;
  107. m_phList = NULL;
  108. m_fInitFailed = FALSE;
  109. try {
  110. if (! InitializeCriticalSectionAndSpinCount(
  111. &m_critSect, 0x80000000))
  112. m_fInitFailed = TRUE;
  113. }
  114. catch (HRESULT hr) {
  115. m_fInitFailed = TRUE;
  116. }
  117. };
  118. virtual ~CHandleList()
  119. {
  120. if (m_fInitFailed)
  121. return;
  122. Clear();
  123. DeleteCriticalSection(&m_critSect);
  124. };
  125. // Properties
  126. // Methods
  127. DWORD Count(void)
  128. {
  129. CCritSect csLock(&m_critSect);
  130. return m_Mac;
  131. };
  132. void
  133. Clear(void)
  134. {
  135. CCritSect csLock(&m_critSect);
  136. if (NULL != m_phList)
  137. {
  138. for (DWORD index = 0; index < m_Mac; index += 1)
  139. if (NULL != m_phList[index].phObject)
  140. delete m_phList[index].phObject;
  141. delete[] m_phList;
  142. m_phList = NULL;
  143. m_Max = 0;
  144. m_Mac = 0;
  145. }
  146. };
  147. CHandle *
  148. Close(
  149. IN HANDLE_TYPE hItem);
  150. HANDLE_TYPE
  151. Add(
  152. IN CHandle *phItem);
  153. CHandle * const
  154. GetQuietly(
  155. IN HANDLE_TYPE hItem);
  156. CHandle * const
  157. Get(
  158. IN HANDLE_TYPE hItem);
  159. HANDLE_TYPE
  160. IndexHandle(
  161. DWORD nItem);
  162. BOOL
  163. InitFailed(void)
  164. { return m_fInitFailed; }
  165. // Operators
  166. CHandle * const
  167. operator[](HANDLE_TYPE hItem)
  168. { return Get(hItem); };
  169. void MarkContentAsBad(BOOL fCancel)
  170. {
  171. CCritSect csLock(&m_critSect);
  172. if (NULL != m_phList)
  173. {
  174. for (DWORD index = 0; index < m_Mac; index += 1)
  175. {
  176. if (NULL != m_phList[index].phObject)
  177. m_phList[index].phObject->MarkAsBad(fCancel);
  178. }
  179. }
  180. }
  181. CHandle *
  182. GetFirst()
  183. {
  184. DWORD index = 0;
  185. while (index < m_Mac)
  186. {
  187. if (NULL != m_phList[index].phObject)
  188. return (m_phList[index].phObject);
  189. index++;
  190. }
  191. return NULL;
  192. }
  193. CHandle *
  194. GetNext(
  195. IN CHandle * phObject)
  196. {
  197. DWORD index = 0;
  198. while (index < m_Mac)
  199. {
  200. if (phObject == m_phList[index].phObject)
  201. break;
  202. index++;
  203. }
  204. if (index < m_Mac)
  205. {
  206. index++;
  207. while (index < m_Mac)
  208. {
  209. if (NULL != m_phList[index].phObject)
  210. return (m_phList[index].phObject);
  211. index++;
  212. }
  213. }
  214. return NULL;
  215. }
  216. protected:
  217. struct HandlePtr
  218. {
  219. CHandle *phObject;
  220. DWORD dwCount;
  221. };
  222. // Properties
  223. DWORD
  224. m_dwId; // Id number of handle list.
  225. DWORD
  226. m_Max, // Number of element slots available.
  227. m_Mac; // Number of element slots used.
  228. HandlePtr *
  229. m_phList; // The elements.
  230. CRITICAL_SECTION
  231. m_critSect; // Handle list access control.
  232. BOOL
  233. m_fInitFailed; // InitCritSec failed in constructor
  234. // Methods
  235. HandlePtr *
  236. GetHandlePtr(
  237. IN HANDLE_TYPE hItem)
  238. const;
  239. };
  240. /*++
  241. Close:
  242. This routine closes an item in the handle array.
  243. Arguments:
  244. hItem - Supplies the handle to the object to be closed.
  245. Throws:
  246. ERROR_INVALID_HANDLE - The supplied handle value is invalid.
  247. Return Value:
  248. The referenced object.
  249. Author:
  250. Doug Barlow (dbarlow) 7/13/1995
  251. --*/
  252. inline CHandle *
  253. CHandleList::Close(
  254. IN HANDLE_TYPE hItem)
  255. {
  256. CHandle *phItem;
  257. CCritSect csLock(&m_critSect);
  258. HandlePtr *pHandlePtr = GetHandlePtr(hItem);
  259. if (NULL == pHandlePtr)
  260. throw (DWORD)ERROR_INVALID_HANDLE;
  261. phItem = pHandlePtr->phObject;
  262. if (NULL == phItem)
  263. throw (DWORD)ERROR_INVALID_HANDLE;
  264. pHandlePtr->phObject = NULL;
  265. pHandlePtr->dwCount += 1;
  266. return phItem;
  267. }
  268. /*++
  269. Add:
  270. This method adds an item to the Handle list.
  271. Arguments:
  272. pvItem - Supplies the value to be added to the list.
  273. Return Value:
  274. The resultant handle of the Add operation.
  275. Author:
  276. Doug Barlow (dbarlow) 10/10/1995
  277. --*/
  278. inline HANDLE_TYPE
  279. CHandleList::Add(
  280. IN CHandle *phItem)
  281. {
  282. DWORD index;
  283. HandlePtr * pHndl = NULL;
  284. //
  285. // Look for a vacant handle slot. We look through m_Max instead of m_Mac,
  286. // so that if all the official ones are used, we fall into unused territory.
  287. //
  288. CCritSect csLock(&m_critSect);
  289. for (index = 0; index < m_Max; index += 1)
  290. {
  291. pHndl = &m_phList[index];
  292. if (NULL == pHndl->phObject)
  293. break;
  294. pHndl = NULL;
  295. }
  296. //
  297. // Make sure the array was big enough.
  298. //
  299. if (NULL == pHndl)
  300. {
  301. DWORD newSize = (0 == m_Max ? 4 : m_Max * 2);
  302. if ((HANDLE_INDEX_MASK >> HANDLE_INDEX_OFFSET) < newSize)
  303. throw (DWORD)ERROR_OUTOFMEMORY;
  304. pHndl = new HandlePtr[newSize];
  305. if (NULL == pHndl)
  306. throw (DWORD)ERROR_OUTOFMEMORY;
  307. if (NULL != m_phList)
  308. {
  309. CopyMemory(pHndl, m_phList, sizeof(HandlePtr) * m_Mac);
  310. delete[] m_phList;
  311. }
  312. ZeroMemory(&pHndl[m_Mac], sizeof(HandlePtr) * (newSize - m_Mac));
  313. m_phList = pHndl;
  314. m_Max = (DWORD)newSize;
  315. index = m_Mac++;
  316. pHndl = &m_phList[index];
  317. }
  318. else
  319. {
  320. if (m_Mac <= index)
  321. m_Mac = index + 1;
  322. }
  323. //
  324. // Cross index the list element and the object.
  325. //
  326. ASSERT(NULL == pHndl->phObject);
  327. pHndl->phObject = phItem;
  328. if (0 == pHndl->dwCount)
  329. pHndl->dwCount = 1;
  330. phItem->m_dwCount = (DWORD)(pHndl->dwCount
  331. & (HANDLE_COUNT_MASK >> HANDLE_COUNT_OFFSET));
  332. phItem->m_dwIndex = index;
  333. return (HANDLE_TYPE)(
  334. ((((HANDLE_TYPE)m_dwId) << HANDLE_ID_OFFSET) & HANDLE_ID_MASK)
  335. | ((((HANDLE_TYPE)pHndl->dwCount) << HANDLE_COUNT_OFFSET) & HANDLE_COUNT_MASK)
  336. | ((((HANDLE_TYPE)index) << HANDLE_INDEX_OFFSET) & HANDLE_INDEX_MASK));
  337. }
  338. /*++
  339. GetQuietly:
  340. This method returns the element at the given handle. If the handle is
  341. invalid, it returns NULL. It does not expand the array.
  342. Arguments:
  343. hItem - Supplies the index into the list.
  344. Return Value:
  345. The value stored at that handle in the list, or NULL if the handle is
  346. invalid.
  347. Author:
  348. Doug Barlow (dbarlow) 7/13/1995
  349. --*/
  350. inline CHandle * const
  351. CHandleList::GetQuietly(
  352. HANDLE_TYPE hItem)
  353. {
  354. CCritSect csLock(&m_critSect);
  355. HandlePtr *pHandlePtr = GetHandlePtr(hItem);
  356. if (NULL == pHandlePtr)
  357. return NULL;
  358. return pHandlePtr->phObject;
  359. }
  360. /*++
  361. Get:
  362. This method returns the element at the given handle. If the handle is
  363. invalid, it throws an error. It does not expand the array.
  364. Arguments:
  365. hItem - Supplies the index into the list.
  366. Return Value:
  367. The value stored at that handle in the list.
  368. Throws:
  369. ERROR_INVALID_HANDLE - Invalid handle value.
  370. Author:
  371. Doug Barlow (dbarlow) 7/13/1995
  372. --*/
  373. inline CHandle * const
  374. CHandleList::Get(
  375. HANDLE_TYPE hItem)
  376. {
  377. CCritSect csLock(&m_critSect);
  378. HandlePtr *pHandlePtr = GetHandlePtr(hItem);
  379. if (NULL == pHandlePtr)
  380. throw (DWORD)ERROR_INVALID_HANDLE;
  381. return pHandlePtr->phObject;
  382. }
  383. /*++
  384. GetHandlePtr:
  385. This routine finds the HandlePtr structure corresponding to a given handle.
  386. Arguments:
  387. hItem supplies the handle to look up.
  388. Return Value:
  389. The address of the HandlePtr structure corresponding to the handle, or NULL
  390. if none exists.
  391. Author:
  392. Doug Barlow (dbarlow) 5/9/1996
  393. --*/
  394. inline CHandleList::HandlePtr *
  395. CHandleList::GetHandlePtr(
  396. HANDLE_TYPE hItem)
  397. const
  398. {
  399. try
  400. {
  401. HandlePtr *pHandlePtr;
  402. DWORD_PTR dwItem = (DWORD_PTR)hItem;
  403. DWORD dwId = (DWORD)((dwItem & HANDLE_ID_MASK) >> HANDLE_ID_OFFSET);
  404. DWORD dwCount = (DWORD)((dwItem & HANDLE_COUNT_MASK) >> HANDLE_COUNT_OFFSET);
  405. DWORD dwIndex = (DWORD)((dwItem & HANDLE_INDEX_MASK) >> HANDLE_INDEX_OFFSET);
  406. if (dwId != (m_dwId & (HANDLE_ID_MASK >> HANDLE_ID_OFFSET))
  407. || (m_Mac <= dwIndex))
  408. return NULL;
  409. pHandlePtr = &m_phList[dwIndex];
  410. if (dwCount
  411. != (pHandlePtr->dwCount
  412. & (HANDLE_ID_MASK >> HANDLE_ID_OFFSET)))
  413. return NULL;
  414. return pHandlePtr;
  415. }
  416. catch (...)
  417. {
  418. // Swallow the error.
  419. }
  420. return NULL;
  421. }
  422. /*++
  423. IndexHandle:
  424. This method converts an index into a handle. The handle is NULL if there is
  425. no element stored at that index.
  426. Arguments:
  427. nItem supplies the index of the object to reference.
  428. Return Value:
  429. The handle of the object, or NULL if there is no object at that index.
  430. Throws:
  431. None
  432. Author:
  433. Doug Barlow (dbarlow) 1/3/1997
  434. --*/
  435. inline HANDLE_TYPE
  436. CHandleList::IndexHandle(
  437. DWORD nItem)
  438. {
  439. HANDLE_TYPE hItem = NULL;
  440. HandlePtr * pHndl;
  441. CCritSect csLock(&m_critSect);
  442. if (m_Mac > nItem)
  443. {
  444. pHndl = &m_phList[nItem];
  445. if (NULL != pHndl->phObject)
  446. {
  447. hItem =
  448. ((((HANDLE_TYPE)m_dwId) << HANDLE_ID_OFFSET) & HANDLE_ID_MASK)
  449. | ((((HANDLE_TYPE)pHndl->dwCount) << HANDLE_COUNT_OFFSET) & HANDLE_COUNT_MASK)
  450. | ((((HANDLE_TYPE)nItem) << HANDLE_INDEX_OFFSET) & HANDLE_INDEX_MASK);
  451. }
  452. }
  453. return hItem;
  454. }
  455. #endif // _HANDLES_H_