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.

396 lines
10 KiB

  1. /*==========================================================================
  2. *
  3. * Copyright (C) 2001-2002 Microsoft Corporation. All Rights Reserved.
  4. *
  5. * File: HandleTable.cpp
  6. * Content: HandleTable Object
  7. *
  8. * History:
  9. * Date By Reason
  10. * ==== == ======
  11. * 07/21/2001 masonb Created
  12. *
  13. *
  14. ***************************************************************************/
  15. #include "dncmni.h"
  16. //**********************************************************************
  17. // Constant definitions
  18. //**********************************************************************
  19. // Our handle table will have a maximum of 0xFFFFFF slots, and will keep
  20. // uniqueness for 256 uses of a particular slot.
  21. #define HANDLETABLE_INDEX_MASK 0x00FFFFFF
  22. #define HANDLETABLE_VERSION_MASK 0xFF000000
  23. #define HANDLETABLE_VERSION_SHIFT 24
  24. //**********************************************************************
  25. // Macro definitions
  26. //**********************************************************************
  27. #define CONSTRUCT_DPNHANDLE(i,v) ((i & HANDLETABLE_INDEX_MASK) | (((DWORD)v << HANDLETABLE_VERSION_SHIFT) & HANDLETABLE_VERSION_MASK))
  28. #define DECODE_HANDLETABLE_INDEX(h) (h & HANDLETABLE_INDEX_MASK)
  29. #define VERIFY_HANDLETABLE_VERSION(h,v) ((h & HANDLETABLE_VERSION_MASK) == ((DWORD)v << HANDLETABLE_VERSION_SHIFT))
  30. #define INVALID_INDEX(i) ((i == 0) || (i >= m_dwNumEntries))
  31. //**********************************************************************
  32. // Structure definitions
  33. //**********************************************************************
  34. //**********************************************************************
  35. // Variable definitions
  36. //**********************************************************************
  37. //**********************************************************************
  38. // Function prototypes
  39. //**********************************************************************
  40. //**********************************************************************
  41. // Function definitions
  42. //**********************************************************************
  43. #undef DPF_MODNAME
  44. #define DPF_MODNAME "CHandleTable::CHandleTable"
  45. CHandleTable::CHandleTable()
  46. {
  47. DEBUG_ONLY(m_fInitialized = FALSE);
  48. };
  49. #undef DPF_MODNAME
  50. #define DPF_MODNAME "CHandleTable::~CHandleTable"
  51. CHandleTable::~CHandleTable()
  52. {
  53. #ifdef DBG
  54. DNASSERT(!m_fInitialized);
  55. #endif // DBG
  56. };
  57. #undef DPF_MODNAME
  58. #define DPF_MODNAME "CHandleTable::Lock"
  59. void CHandleTable::Lock( void )
  60. {
  61. #ifdef DBG
  62. DNASSERT(m_fInitialized);
  63. #endif // DBG
  64. DNEnterCriticalSection(&m_cs);
  65. };
  66. #undef DPF_MODNAME
  67. #define DPF_MODNAME "CHandleTable::Unlock"
  68. void CHandleTable::Unlock( void )
  69. {
  70. #ifdef DBG
  71. DNASSERT(m_fInitialized);
  72. #endif // DBG
  73. DNLeaveCriticalSection(&m_cs);
  74. };
  75. #undef DPF_MODNAME
  76. #define DPF_MODNAME "CHandleTable::Initialize"
  77. HRESULT CHandleTable::Initialize( void )
  78. {
  79. memset(this, 0, sizeof(CHandleTable));
  80. if (!DNInitializeCriticalSection(&m_cs))
  81. {
  82. DPFERR("Failed to initialize Critical Section");
  83. return DPNERR_OUTOFMEMORY;
  84. }
  85. DEBUG_ONLY(m_fInitialized = TRUE);
  86. DPFX(DPFPREP, 5,"[%p] Handle table initialized", this);
  87. return DPN_OK;
  88. };
  89. #undef DPF_MODNAME
  90. #define DPF_MODNAME "CHandleTable::Deinitialize"
  91. void CHandleTable::Deinitialize( void )
  92. {
  93. #ifdef DBG
  94. DNASSERT(m_fInitialized);
  95. m_fInitialized = FALSE;
  96. #endif // DBG
  97. if (m_pTable)
  98. {
  99. DNFree(m_pTable);
  100. m_pTable = NULL;
  101. }
  102. DNDeleteCriticalSection(&m_cs);
  103. DPFX(DPFPREP, 5,"[%p] Handle table deinitialized", this);
  104. };
  105. #ifdef DPNBUILD_PREALLOCATEDMEMORYMODEL
  106. #undef DPF_MODNAME
  107. #define DPF_MODNAME "CHandleTable::GrowTable"
  108. HRESULT CHandleTable::SetTableSize( const DWORD dwNumEntries )
  109. #else // ! DPNBUILD_PREALLOCATEDMEMORYMODEL
  110. #undef DPF_MODNAME
  111. #define DPF_MODNAME "CHandleTable::GrowTable"
  112. HRESULT CHandleTable::GrowTable( void )
  113. #endif // ! DPNBUILD_PREALLOCATEDMEMORYMODEL
  114. {
  115. _HANDLETABLE_ENTRY *pNewArray;
  116. DWORD dwNewSize;
  117. DWORD dw;
  118. #ifdef DBG
  119. DNASSERT(m_fInitialized);
  120. #endif // DBG
  121. #ifdef DPNBUILD_PREALLOCATEDMEMORYMODEL
  122. DNASSERT(m_dwNumEntries == 0);
  123. DNASSERT( dwNumEntries < (HANDLETABLE_INDEX_MASK - 1) );
  124. dwNewSize = dwNumEntries + 1; // + 1 because we never hand out entry 0
  125. #else // ! DPNBUILD_PREALLOCATEDMEMORYMODEL
  126. // The caller should have taken the lock
  127. AssertCriticalSectionIsTakenByThisThread(&m_cs, TRUE);
  128. //
  129. // Double table size or seed with 2 entries
  130. //
  131. if (m_dwNumEntries == 0)
  132. {
  133. dwNewSize = 2;
  134. }
  135. else
  136. {
  137. // Ensure that we stay below our max size and that
  138. // we don't use all F's as a handle value.
  139. if (m_dwNumEntries == (HANDLETABLE_INDEX_MASK - 1))
  140. {
  141. DPFERR("Handle Table is full!");
  142. DNASSERT(FALSE);
  143. return DPNERR_GENERIC;
  144. }
  145. DNASSERT( m_dwNumEntries < (HANDLETABLE_INDEX_MASK - 1) );
  146. dwNewSize = _MIN(m_dwNumEntries * 2, HANDLETABLE_INDEX_MASK - 1);
  147. }
  148. #endif // ! DPNBUILD_PREALLOCATEDMEMORYMODEL
  149. //
  150. // Allocate new array
  151. //
  152. pNewArray = (_HANDLETABLE_ENTRY*)DNMalloc(sizeof(_HANDLETABLE_ENTRY) * dwNewSize);
  153. if (pNewArray == NULL)
  154. {
  155. DPFERR("Out of memory growing handle table");
  156. return DPNERR_OUTOFMEMORY;
  157. }
  158. #ifndef DPNBUILD_PREALLOCATEDMEMORYMODEL
  159. //
  160. // Copy old array to new array
  161. //
  162. if (m_pTable)
  163. {
  164. // NOTE: On the first Grow this will be memcpy'ing size 0 and then free'ing size 0.
  165. memcpy(pNewArray, m_pTable, m_dwNumEntries * sizeof(_HANDLETABLE_ENTRY));
  166. DNFree(m_pTable);
  167. }
  168. #endif // ! DPNBUILD_PREALLOCATEDMEMORYMODEL
  169. m_pTable = pNewArray;
  170. //
  171. // Free entries at end of new array
  172. //
  173. for (dw = m_dwNumEntries ; dw < dwNewSize - 1 ; dw++ )
  174. {
  175. // Each slot points to the free slot following it
  176. m_pTable[dw].Entry.dwIndex = dw + 1;
  177. m_pTable[dw].bVersion = 0;
  178. }
  179. // The final slot has no slot following it to point to
  180. m_pTable[dwNewSize-1].Entry.dwIndex = 0;
  181. m_pTable[dwNewSize-1].bVersion = 0;
  182. m_dwFirstFreeEntry = m_dwNumEntries;
  183. m_dwNumFreeEntries = dwNewSize - m_dwNumEntries;
  184. m_dwNumEntries = dwNewSize;
  185. m_dwLastFreeEntry = dwNewSize - 1;
  186. #ifndef DPNBUILD_PREALLOCATEDMEMORYMODEL
  187. if (m_dwFirstFreeEntry == 0)
  188. #endif // ! DPNBUILD_PREALLOCATEDMEMORYMODEL
  189. {
  190. // Don't allow 0 as a handle value, so we will waste the first slot
  191. m_dwFirstFreeEntry++;
  192. m_dwNumFreeEntries--;
  193. }
  194. DPFX(DPFPREP, 5,"[%p] Grew handle table to [%d] entries", this, m_dwNumEntries);
  195. return DPN_OK;
  196. };
  197. #undef DPF_MODNAME
  198. #define DPF_MODNAME "CHandleTable::Create"
  199. HRESULT CHandleTable::Create( PVOID const pvData, DPNHANDLE *const pHandle )
  200. {
  201. HRESULT hr;
  202. DWORD dwIndex;
  203. DPNHANDLE handle;
  204. #ifdef DBG
  205. // Data is not allowed to be NULL.
  206. DNASSERT(pvData != NULL);
  207. DNASSERT(pHandle != NULL);
  208. DNASSERT(m_fInitialized);
  209. #endif // DBG
  210. Lock();
  211. // Ensure that we have free entries
  212. if (m_dwNumFreeEntries == 0)
  213. {
  214. #ifdef DPNBUILD_PREALLOCATEDMEMORYMODEL
  215. DPFX(DPFPREP, 0, "No room in handle table!");
  216. DNASSERTX(! "No room in handle table!", 2);
  217. hr = DPNERR_OUTOFMEMORY;
  218. #else // ! DPNBUILD_PREALLOCATEDMEMORYMODEL
  219. hr = GrowTable();
  220. if (hr != DPN_OK)
  221. #endif // ! DPNBUILD_PREALLOCATEDMEMORYMODEL
  222. {
  223. // NOTE: It is important that we not touch *pHandle in the fail case.
  224. // Different layers will initialize this to what they want (0 or
  225. // INVALID_HANDLE_VALUE) and will expect to be able to test against
  226. // that in their fail code.
  227. Unlock();
  228. return hr;
  229. }
  230. }
  231. DNASSERT(m_dwNumFreeEntries != 0);
  232. DNASSERT(m_dwFirstFreeEntry != 0);
  233. dwIndex = m_dwFirstFreeEntry;
  234. handle = CONSTRUCT_DPNHANDLE(dwIndex, m_pTable[dwIndex].bVersion);
  235. // The slot's dwIndex member points to the next free slot. Grab the value of the
  236. // next free entry before overwriting it with pvData.
  237. m_dwFirstFreeEntry = m_pTable[dwIndex].Entry.dwIndex;
  238. m_pTable[dwIndex].Entry.pvData = pvData;
  239. m_dwNumFreeEntries--;
  240. Unlock();
  241. DPFX(DPFPREP, 5,"[%p] Created handle [0x%lx], data [%p]", this, handle, pvData);
  242. DNASSERT(handle != 0);
  243. *pHandle = handle;
  244. return DPN_OK;
  245. }
  246. #undef DPF_MODNAME
  247. #define DPF_MODNAME "CHandleTable::Destroy"
  248. HRESULT CHandleTable::Destroy( const DPNHANDLE handle, PVOID *const ppvData )
  249. {
  250. DWORD dwIndex;
  251. #ifdef DBG
  252. DNASSERT(m_fInitialized);
  253. #endif // DBG
  254. dwIndex = DECODE_HANDLETABLE_INDEX( handle );
  255. Lock();
  256. if (INVALID_INDEX(dwIndex))
  257. {
  258. Unlock();
  259. DPFX(DPFPREP, 1, "Attempt to destroy handle with invalid index (0x%x).", handle);
  260. return DPNERR_INVALIDHANDLE;
  261. }
  262. if (!VERIFY_HANDLETABLE_VERSION(handle, m_pTable[dwIndex].bVersion))
  263. {
  264. Unlock();
  265. DPFERR("Attempt to destroy handle with non-matching version");
  266. return DPNERR_INVALIDHANDLE;
  267. }
  268. DPFX(DPFPREP, 5,"[%p] Destroy handle [0x%lx], data[%p]", this, handle, m_pTable[dwIndex].Entry.pvData);
  269. DNASSERT(m_pTable[dwIndex].Entry.pvData != NULL);
  270. if (ppvData)
  271. {
  272. *ppvData = m_pTable[dwIndex].Entry.pvData;
  273. }
  274. m_pTable[dwIndex].Entry.pvData = NULL;
  275. m_pTable[dwIndex].bVersion++;
  276. if (m_dwNumFreeEntries == 0)
  277. {
  278. DNASSERT(m_dwFirstFreeEntry == 0);
  279. m_dwFirstFreeEntry = dwIndex;
  280. }
  281. else
  282. {
  283. m_pTable[m_dwLastFreeEntry].Entry.dwIndex = dwIndex;
  284. }
  285. m_dwLastFreeEntry = dwIndex;
  286. m_dwNumFreeEntries++;
  287. Unlock();
  288. return DPN_OK;
  289. }
  290. #undef DPF_MODNAME
  291. #define DPF_MODNAME "CHandleTable::Find"
  292. HRESULT CHandleTable::Find( const DPNHANDLE handle, PVOID *const ppvData )
  293. {
  294. DWORD dwIndex;
  295. #ifdef DBG
  296. DNASSERT(ppvData != NULL);
  297. DNASSERT(m_fInitialized);
  298. #endif // DBG
  299. *ppvData = NULL;
  300. dwIndex = DECODE_HANDLETABLE_INDEX( handle );
  301. Lock();
  302. if (INVALID_INDEX(dwIndex))
  303. {
  304. Unlock();
  305. DPFERR("Attempt to lookup handle with invalid index");
  306. return DPNERR_INVALIDHANDLE;
  307. }
  308. if (!VERIFY_HANDLETABLE_VERSION(handle, m_pTable[dwIndex].bVersion))
  309. {
  310. Unlock();
  311. DPFERR("Attempt to lookup handle with non-matching version");
  312. return DPNERR_INVALIDHANDLE;
  313. }
  314. DPFX(DPFPREP, 5,"[%p] Find data for handle [0x%lx], data[%p]", this, handle, m_pTable[dwIndex].Entry.pvData);
  315. DNASSERT(m_pTable[dwIndex].Entry.pvData != NULL);
  316. *ppvData = m_pTable[dwIndex].Entry.pvData;
  317. Unlock();
  318. return DPN_OK;
  319. }