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.

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