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.

261 lines
6.1 KiB

  1. //
  2. // sink.cpp
  3. //
  4. #include "private.h"
  5. #include "sink.h"
  6. #include "strary.h"
  7. //+---------------------------------------------------------------------------
  8. //
  9. // GenericAdviseSink
  10. //
  11. // Never returns cookies with the high bit set, use this behavior to chain
  12. // other cookie allocators along with GenericAdviseSink....
  13. //----------------------------------------------------------------------------
  14. HRESULT GenericAdviseSink(REFIID riid, IUnknown *punk, const IID **rgiidConnectionPts,
  15. CStructArray<GENERICSINK> *rgSinkArrays, UINT cConnectionPts,
  16. DWORD *pdwCookie, GENERICSINK **ppSink /* = NULL */)
  17. {
  18. UINT iArray;
  19. int iSink;
  20. UINT cSinks;
  21. DWORD dwCookie;
  22. DWORD dw;
  23. IUnknown *punkSink;
  24. GENERICSINK *pgs;
  25. CStructArray<GENERICSINK> *rgSinks;
  26. Assert(cConnectionPts < 128); // 127 maximum IIDs
  27. if (pdwCookie == NULL)
  28. return E_INVALIDARG;
  29. *pdwCookie = GENERIC_ERROR_COOKIE;
  30. if (punk == NULL)
  31. return E_INVALIDARG;
  32. for (iArray=0; iArray<cConnectionPts; iArray++)
  33. {
  34. if (IsEqualIID(riid, *rgiidConnectionPts[iArray]))
  35. break;
  36. }
  37. if (iArray == cConnectionPts)
  38. return CONNECT_E_CANNOTCONNECT;
  39. rgSinks = &rgSinkArrays[iArray];
  40. cSinks = rgSinks->Count();
  41. if (cSinks >= 0x00ffffff)
  42. return CONNECT_E_ADVISELIMIT; // 16M sinks max
  43. if (FAILED(punk->QueryInterface(riid, (void **)&punkSink)))
  44. return E_FAIL;
  45. // calculate a cookie
  46. if (cSinks == 0)
  47. {
  48. dwCookie = 0;
  49. iSink = 0;
  50. }
  51. else
  52. {
  53. // we are guarenteed to break from the loop because we already know
  54. // that there are fewer than 17M entries
  55. dwCookie = 0x00ffffff;
  56. for (iSink = cSinks-1; iSink>=0; iSink--)
  57. {
  58. dw = rgSinks->GetPtr(iSink)->dwCookie;
  59. if (dwCookie > dw)
  60. {
  61. iSink++;
  62. dwCookie = dw + 1; // keep the cookie as low as possible
  63. break;
  64. }
  65. dwCookie = dw - 1;
  66. }
  67. Assert(dwCookie <= 0x00ffffff);
  68. }
  69. if (!rgSinks->Insert(iSink, 1))
  70. {
  71. punkSink->Release();
  72. return E_OUTOFMEMORY;
  73. }
  74. pgs = rgSinks->GetPtr(iSink);
  75. pgs->pSink = punkSink; // already AddRef'd from the qi
  76. pgs->dwCookie = dwCookie;
  77. *pdwCookie = (iArray << 24) | dwCookie;
  78. if (ppSink != NULL)
  79. {
  80. *ppSink = pgs;
  81. }
  82. return S_OK;
  83. }
  84. //+---------------------------------------------------------------------------
  85. //
  86. // GenericUnadviseSink
  87. //
  88. //----------------------------------------------------------------------------
  89. HRESULT GenericUnadviseSink(CStructArray<GENERICSINK> *rgSinkArrays, UINT cConnectionPts, DWORD dwCookie, UINT_PTR *puPrivate /* = NULL */)
  90. {
  91. UINT iArray;
  92. int iMin;
  93. int iMax;
  94. int iMid;
  95. HRESULT hr;
  96. GENERICSINK *pgs;
  97. CStructArray<GENERICSINK> *rgSinks;
  98. if (dwCookie == GENERIC_ERROR_COOKIE)
  99. return E_INVALIDARG;
  100. iArray = GenericCookieToGUIDIndex(dwCookie);
  101. if (iArray >= cConnectionPts)
  102. return CONNECT_E_NOCONNECTION;
  103. dwCookie &= 0x00ffffff;
  104. rgSinks = &rgSinkArrays[iArray];
  105. hr = CONNECT_E_NOCONNECTION;
  106. iMid = -1;
  107. iMin = 0;
  108. iMax = rgSinks->Count();
  109. while (iMin < iMax)
  110. {
  111. iMid = (iMin + iMax) / 2;
  112. pgs = rgSinks->GetPtr(iMid);
  113. if (pgs->dwCookie < dwCookie)
  114. {
  115. iMin = iMid + 1;
  116. }
  117. else if (pgs->dwCookie > dwCookie)
  118. {
  119. iMax = iMid;
  120. }
  121. else // pgs->dwCookie == dwCookie
  122. {
  123. if (puPrivate != NULL)
  124. {
  125. *puPrivate = pgs->uPrivate;
  126. }
  127. pgs->pSink->Release();
  128. rgSinks->Remove(iMid, 1);
  129. hr = S_OK;
  130. break;
  131. }
  132. }
  133. return hr;
  134. }
  135. //+---------------------------------------------------------------------------
  136. //
  137. // RequestCookie
  138. //
  139. //----------------------------------------------------------------------------
  140. HRESULT RequestCookie(CStructArray<DWORD> *rgCookies, DWORD *pdwCookie)
  141. {
  142. DWORD dwCookie;
  143. int iId;
  144. UINT cCookies = rgCookies->Count();
  145. DWORD *pdw;
  146. // calculate a cookie
  147. if (cCookies == 0)
  148. {
  149. dwCookie = 0;
  150. iId = 0;
  151. }
  152. else
  153. {
  154. // we are guarenteed to break from the loop because we already know
  155. // that there are fewer than 17M entries
  156. dwCookie = 0x7fffffff;
  157. for (iId = cCookies-1; iId >= 0; iId--)
  158. {
  159. DWORD dw = *(rgCookies->GetPtr(iId));
  160. if (dwCookie > dw)
  161. {
  162. iId++;
  163. dwCookie = dw + 1; // keep the cookie as low as possible
  164. break;
  165. }
  166. dwCookie = dw - 1;
  167. }
  168. Assert(dwCookie <= 0x00ffffff);
  169. }
  170. if (!rgCookies->Insert(iId, 1))
  171. {
  172. return E_OUTOFMEMORY;
  173. }
  174. pdw = rgCookies->GetPtr(iId);
  175. *pdw = dwCookie;
  176. dwCookie |= 0x80000000;
  177. *pdwCookie = dwCookie;
  178. return S_OK;
  179. }
  180. //+---------------------------------------------------------------------------
  181. //
  182. // ReleaseCookie
  183. //
  184. //----------------------------------------------------------------------------
  185. HRESULT ReleaseCookie(CStructArray<DWORD> *rgCookies, DWORD dwCookie)
  186. {
  187. int iMin;
  188. int iMax;
  189. int iMid;
  190. HRESULT hr = CONNECT_E_NOCONNECTION;
  191. if (!(dwCookie & 0x80000000))
  192. return hr;
  193. dwCookie &= 0x7fffffff;
  194. iMid = -1;
  195. iMin = 0;
  196. iMax = rgCookies->Count();
  197. while (iMin < iMax)
  198. {
  199. iMid = (iMin + iMax) / 2;
  200. DWORD dw = *(rgCookies->GetPtr(iMid));
  201. if (dw < dwCookie)
  202. {
  203. iMin = iMid + 1;
  204. }
  205. else if (dw > dwCookie)
  206. {
  207. iMax = iMid;
  208. }
  209. else // dw == dwCookie
  210. {
  211. rgCookies->Remove(iMid, 1);
  212. hr = S_OK;
  213. break;
  214. }
  215. }
  216. return hr;
  217. }