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.

372 lines
8.7 KiB

  1. #include "pch.hxx"
  2. #include "voidlist.h"
  3. #include "msoedbg.h"
  4. #include <winbase.h>
  5. struct CNode
  6. {
  7. CNode *m_pNodes[LD_LASTDIRECTION];
  8. void *m_pValue;
  9. DWORD m_dwHandle;
  10. CNode() : m_pValue(NULL)
  11. {
  12. m_pNodes[LD_FORWARD] = NULL;
  13. m_pNodes[LD_REVERSE] = NULL;
  14. }
  15. CNode* GetNext() {return m_pNodes[LD_FORWARD];}
  16. CNode* GetPrev() {return m_pNodes[LD_REVERSE];}
  17. void SetNext(CNode *pNode) {m_pNodes[LD_FORWARD] = pNode;}
  18. void SetPrev(CNode *pNode) {m_pNodes[LD_REVERSE] = pNode;}
  19. };
  20. // *************************************************
  21. CVoidPtrList::CVoidPtrList() : m_cRefCount(1), m_cCount(0), m_dwCookie(0),
  22. m_pCompareFunc(NULL), m_pFreeItemFunc(NULL), m_fInited(false)
  23. {
  24. SetHead(NULL);
  25. SetTail(NULL);
  26. InitializeCriticalSection(&m_rCritSect);
  27. }
  28. // *************************************************
  29. CVoidPtrList::~CVoidPtrList()
  30. {
  31. ClearList();
  32. DeleteCriticalSection(&m_rCritSect);
  33. }
  34. // ******************************************************
  35. ULONG CVoidPtrList::AddRef(void)
  36. {
  37. return InterlockedIncrement(&m_cRefCount);
  38. }
  39. // ******************************************************
  40. ULONG CVoidPtrList::Release(void)
  41. {
  42. LONG cRef = InterlockedDecrement(&m_cRefCount);
  43. if (0 == cRef)
  44. delete this;
  45. return S_OK;
  46. }
  47. // *************************************************
  48. HRESULT CVoidPtrList::Init(IVPL_COMPAREFUNCTYPE pCompareFunc, DWORD_PTR dwCookie,
  49. IVPL_FREEITEMFUNCTYPE pFreeItemFunc, DWORD dwInitSize)
  50. {
  51. HRESULT hr = S_OK;
  52. EnterCriticalSection(&m_rCritSect);
  53. if (!m_fInited)
  54. {
  55. m_dwCookie = dwCookie;
  56. m_pCompareFunc = pCompareFunc;
  57. m_pFreeItemFunc = pFreeItemFunc;
  58. //~~~ Need to do something with dwInitSize.
  59. }
  60. else
  61. hr = E_FAIL;
  62. LeaveCriticalSection(&m_rCritSect);
  63. return hr;
  64. }
  65. // *************************************************
  66. HRESULT CVoidPtrList::ClearList(void)
  67. {
  68. EnterCriticalSection(&m_rCritSect);
  69. CNode *pCurr = GetHead(),
  70. *pNext;
  71. SetHead(NULL);
  72. SetTail(NULL);
  73. m_cCount = 0;
  74. if (m_pFreeItemFunc)
  75. while (pCurr)
  76. {
  77. pNext = pCurr->GetNext();
  78. m_pFreeItemFunc(pCurr->m_pValue);
  79. delete pCurr;
  80. pCurr = pNext;
  81. }
  82. else
  83. while (pCurr)
  84. {
  85. pNext = pCurr->GetNext();
  86. delete pCurr;
  87. pCurr = pNext;
  88. }
  89. LeaveCriticalSection(&m_rCritSect);
  90. return S_OK;
  91. }
  92. // *************************************************
  93. HRESULT CVoidPtrList::AddItem(LPVOID ptr, DWORD *pdwHandle)
  94. {
  95. HRESULT hr = S_OK;
  96. Assert(ptr);
  97. EnterCriticalSection(&m_rCritSect);
  98. CNode *pNewNode = new CNode;
  99. if (pNewNode)
  100. {
  101. pNewNode->m_pValue = ptr;
  102. pNewNode->m_dwHandle = GetNewHandle();
  103. if (m_pCompareFunc)
  104. SortedAddItem(pNewNode);
  105. else
  106. NonSortedAddItem(pNewNode);
  107. }
  108. else
  109. hr = E_OUTOFMEMORY;
  110. LeaveCriticalSection(&m_rCritSect);
  111. if (pNewNode)
  112. *pdwHandle = pNewNode->m_dwHandle;
  113. return hr;
  114. }
  115. // *************************************************
  116. void CVoidPtrList::SortedAddItem(CNode *pNode)
  117. {
  118. if (0 == m_cCount++)
  119. {
  120. SetHead(pNode);
  121. SetTail(pNode);
  122. }
  123. else
  124. {
  125. CNode *compAgainstNode = GetHead();
  126. void *pValue = pNode->m_pValue;
  127. while (compAgainstNode)
  128. {
  129. bool ALessThanB;
  130. m_pCompareFunc(pValue, compAgainstNode->m_pValue, &ALessThanB, m_dwCookie);
  131. if (ALessThanB)
  132. break;
  133. else
  134. compAgainstNode = compAgainstNode->GetNext();
  135. }
  136. // Insert at Tail
  137. if (!compAgainstNode)
  138. {
  139. GetTail()->SetNext(pNode);
  140. pNode->SetPrev(GetTail());
  141. SetTail(pNode);
  142. }
  143. // Insert at Head
  144. else if (!compAgainstNode->GetPrev())
  145. {
  146. GetHead()->SetPrev(pNode);
  147. pNode->SetNext(GetHead());
  148. SetHead(pNode);
  149. }
  150. // Insert in middle
  151. else
  152. {
  153. CNode *prev = compAgainstNode->GetPrev();
  154. pNode->SetNext(compAgainstNode);
  155. pNode->SetPrev(prev);
  156. prev->SetNext(pNode);
  157. compAgainstNode->SetPrev(pNode);
  158. }
  159. }
  160. }
  161. // *************************************************
  162. void CVoidPtrList::NonSortedAddItem(CNode *pNode)
  163. {
  164. if (0 == m_cCount)
  165. {
  166. SetHead(pNode);
  167. SetTail(pNode);
  168. }
  169. else
  170. {
  171. GetHead()->SetPrev(pNode);
  172. pNode->SetNext(GetHead());
  173. SetHead(pNode);
  174. }
  175. m_cCount++;
  176. }
  177. // *************************************************
  178. HRESULT CVoidPtrList::RemoveItem(DWORD dwHandle)
  179. {
  180. CNode *pCurr = FindItem(dwHandle);
  181. if (pCurr)
  182. {
  183. EnterCriticalSection(&m_rCritSect);
  184. CNode *pNext = pCurr->GetNext();
  185. CNode *pPrev = pCurr->GetPrev();
  186. if (pNext)
  187. pNext->SetPrev(pPrev);
  188. else
  189. SetTail(pPrev);
  190. if (pPrev)
  191. pPrev->SetNext(pNext);
  192. else
  193. SetHead(pNext);
  194. if (m_pFreeItemFunc)
  195. m_pFreeItemFunc(pCurr->m_pValue);
  196. delete pCurr;
  197. m_cCount--;
  198. LeaveCriticalSection(&m_rCritSect);
  199. }
  200. return S_OK;
  201. }
  202. // *************************************************
  203. HRESULT CVoidPtrList::GetNext(LISTDIRECTION bDirection, LPVOID *pptr, DWORD *pdwHandle)
  204. {
  205. CNode *pCurr = FindItem(*pdwHandle);
  206. HRESULT hr = S_OK;
  207. EnterCriticalSection(&m_rCritSect);
  208. if (pCurr)
  209. pCurr = pCurr->m_pNodes[bDirection];
  210. else
  211. pCurr = m_pEnds[bDirection];
  212. if (pCurr)
  213. {
  214. *pptr = pCurr->m_pValue;
  215. *pdwHandle = pCurr->m_dwHandle;
  216. }
  217. else
  218. {
  219. *pptr = NULL;
  220. hr = E_FAIL;
  221. }
  222. LeaveCriticalSection(&m_rCritSect);
  223. return hr;
  224. }
  225. // *************************************************
  226. HRESULT CVoidPtrList::SkipNext(LISTDIRECTION bDirection, DWORD *pdwHandle)
  227. {
  228. CNode *pCurr = FindItem(*pdwHandle);
  229. EnterCriticalSection(&m_rCritSect);
  230. if (pCurr)
  231. pCurr = pCurr->m_pNodes[bDirection];
  232. else
  233. pCurr = m_pEnds[bDirection];
  234. if (pCurr)
  235. *pdwHandle = pCurr->m_dwHandle;
  236. LeaveCriticalSection(&m_rCritSect);
  237. if (pCurr)
  238. return S_OK;
  239. return E_FAIL;
  240. }
  241. // *************************************************
  242. HRESULT CVoidPtrList::Resort(void)
  243. {
  244. EnterCriticalSection(&m_rCritSect);
  245. if (m_pCompareFunc && (m_cCount > 1))
  246. {
  247. CNode *pHead = GetHead();
  248. m_cCount = 0;
  249. SetHead(NULL);
  250. SetTail(NULL);
  251. while (pHead)
  252. {
  253. CNode *pNext = pHead->GetNext();
  254. pHead->SetPrev(NULL);
  255. pHead->SetNext(NULL);
  256. SortedAddItem(pHead);
  257. pHead = pNext;
  258. }
  259. }
  260. LeaveCriticalSection(&m_rCritSect);
  261. return S_OK;
  262. }
  263. // *************************************************
  264. CNode* CVoidPtrList::FindItem(DWORD dwHandle)
  265. {
  266. CNode *pHead = GetHead();
  267. for (pHead = GetHead(); NULL != pHead; pHead = pHead->GetNext())
  268. {
  269. if (dwHandle == pHead->m_dwHandle)
  270. break;
  271. }
  272. return pHead;
  273. }
  274. // *************************************************
  275. DWORD CVoidPtrList::GetNewHandle()
  276. {
  277. CNode *pHead = GetHead();
  278. DWORD dwHandle = 0;
  279. for (dwHandle = HANDLE_START; HANDLE_END > dwHandle; dwHandle++)
  280. {
  281. for (pHead = GetHead(); NULL != pHead; pHead = pHead->GetNext())
  282. {
  283. if (dwHandle == pHead->m_dwHandle)
  284. break;
  285. }
  286. if (NULL == pHead)
  287. break;
  288. }
  289. return dwHandle;
  290. }
  291. // =================================================
  292. // Static functions
  293. // =================================================
  294. HRESULT CVoidPtrList::CreateInstance(CVoidPtrList** ppList)
  295. {
  296. HRESULT hr = S_OK;
  297. // Create me
  298. CVoidPtrList *pNew = new CVoidPtrList;
  299. if (NULL == pNew)
  300. hr = E_OUTOFMEMORY;
  301. *ppList = pNew;
  302. // Done
  303. return hr;
  304. }
  305. HRESULT IVoidPtrList_CreateInstance(IVoidPtrList** ppList)
  306. {
  307. CVoidPtrList* pList;
  308. HRESULT hr = CVoidPtrList::CreateInstance(&pList);
  309. if (SUCCEEDED(hr))
  310. *ppList = static_cast<IVoidPtrList*>(pList);
  311. else
  312. *ppList = NULL;
  313. return hr;
  314. }