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.

386 lines
8.2 KiB

  1. ///////////////////////////////////////////////////////////////////////////////
  2. //
  3. // Copyright (c) Microsoft Corporation.
  4. //
  5. // SYNOPSIS
  6. //
  7. // Defines the class Request.
  8. //
  9. ///////////////////////////////////////////////////////////////////////////////
  10. #include <polcypch.h>
  11. #include <iasattr.h>
  12. #include <sdoias.h>
  13. #include <request.h>
  14. #include <new>
  15. PIASATTRIBUTE Request::findFirst(DWORD id) const throw ()
  16. {
  17. for (PIASATTRIBUTE* a = begin; a != end; ++a)
  18. {
  19. if ((*a)->dwId == id) { return *a; }
  20. }
  21. return NULL;
  22. }
  23. Request* Request::narrow(IUnknown* pUnk) throw ()
  24. {
  25. Request* request = NULL;
  26. if (pUnk)
  27. {
  28. HRESULT hr = pUnk->QueryInterface(
  29. __uuidof(Request),
  30. (PVOID*)&request
  31. );
  32. if (SUCCEEDED(hr))
  33. {
  34. request->GetUnknown()->Release();
  35. }
  36. }
  37. return request;
  38. }
  39. STDMETHODIMP Request::get_Source(IRequestSource** pVal)
  40. {
  41. if (*pVal = source) { source->AddRef(); }
  42. return S_OK;
  43. }
  44. STDMETHODIMP Request::put_Source(IRequestSource* newVal)
  45. {
  46. if (source) { source->Release(); }
  47. if (source = newVal) { source->AddRef(); }
  48. return S_OK;
  49. }
  50. STDMETHODIMP Request::get_Protocol(IASPROTOCOL *pVal)
  51. {
  52. *pVal = protocol;
  53. return S_OK;
  54. }
  55. STDMETHODIMP Request::put_Protocol(IASPROTOCOL newVal)
  56. {
  57. protocol = newVal;
  58. return S_OK;
  59. }
  60. STDMETHODIMP Request::get_Request(LONG *pVal)
  61. {
  62. *pVal = (LONG)request;
  63. return S_OK;
  64. }
  65. STDMETHODIMP Request::put_Request(LONG newVal)
  66. {
  67. request = (IASREQUEST)newVal;
  68. return S_OK;
  69. }
  70. STDMETHODIMP Request::get_Response(LONG *pVal)
  71. {
  72. *pVal = (LONG)response;
  73. return S_OK;
  74. }
  75. STDMETHODIMP Request::get_Reason(LONG *pVal)
  76. {
  77. *pVal = (LONG)reason;
  78. return S_OK;
  79. }
  80. STDMETHODIMP Request::SetResponse(IASRESPONSE eResponse, LONG lReason)
  81. {
  82. response = eResponse;
  83. reason = (IASREASON)lReason;
  84. return S_OK;
  85. }
  86. STDMETHODIMP Request::ReturnToSource(IASREQUESTSTATUS eStatus)
  87. {
  88. return source ? source->OnRequestComplete(this, eStatus) : S_OK;
  89. }
  90. HRESULT Request::AddAttributes(
  91. DWORD dwPosCount,
  92. PATTRIBUTEPOSITION pPositions
  93. )
  94. {
  95. if (!reserve(size() + dwPosCount))
  96. {
  97. return E_OUTOFMEMORY;
  98. }
  99. for ( ; dwPosCount; --dwPosCount, ++pPositions)
  100. {
  101. IASAttributeAddRef(pPositions->pAttribute);
  102. *end++ = pPositions->pAttribute;
  103. }
  104. return S_OK;
  105. }
  106. HRESULT Request::RemoveAttributes(
  107. DWORD dwPosCount,
  108. PATTRIBUTEPOSITION pPositions
  109. )
  110. {
  111. for ( ; dwPosCount; --dwPosCount, ++pPositions)
  112. {
  113. PIASATTRIBUTE* pos = find(pPositions->pAttribute);
  114. if (pos != 0)
  115. {
  116. IASAttributeRelease(*pos);
  117. --end;
  118. memmove(pos, pos + 1, (end - pos) * sizeof(PIASATTRIBUTE));
  119. }
  120. }
  121. return S_OK;
  122. }
  123. HRESULT Request::RemoveAttributesByType(
  124. DWORD dwAttrIDCount,
  125. DWORD *lpdwAttrIDs
  126. )
  127. {
  128. for ( ; dwAttrIDCount; ++lpdwAttrIDs, --dwAttrIDCount)
  129. {
  130. for (PIASATTRIBUTE* i = begin; i != end; )
  131. {
  132. if ((*i)->dwId == *lpdwAttrIDs)
  133. {
  134. IASAttributeRelease(*i);
  135. --end;
  136. memmove(i, i + 1, (end - i) * sizeof(PIASATTRIBUTE));
  137. }
  138. else
  139. {
  140. ++i;
  141. }
  142. }
  143. }
  144. return S_OK;
  145. }
  146. HRESULT Request::GetAttributeCount(
  147. DWORD *lpdwCount
  148. )
  149. {
  150. *lpdwCount = size();
  151. return S_OK;
  152. }
  153. HRESULT Request::GetAttributes(
  154. DWORD *lpdwPosCount,
  155. PATTRIBUTEPOSITION pPositions,
  156. DWORD dwAttrIDCount,
  157. DWORD *lpdwAttrIDs
  158. )
  159. {
  160. HRESULT hr = S_OK;
  161. DWORD count = 0;
  162. // End of the caller supplied array.
  163. PATTRIBUTEPOSITION stop = pPositions + *lpdwPosCount;
  164. // Next struct to be filled.
  165. PATTRIBUTEPOSITION next = pPositions;
  166. // Force at least one iteration of the for loop.
  167. if (!lpdwAttrIDs) { dwAttrIDCount = 1; }
  168. // Iterate through the desired attribute IDs.
  169. for ( ; dwAttrIDCount; ++lpdwAttrIDs, --dwAttrIDCount)
  170. {
  171. // Iterate through the request's attribute collection.
  172. for (PIASATTRIBUTE* i = begin; i != end; ++i)
  173. {
  174. // Did the caller ask for all the attributes ?
  175. // If not, is this a match for one of the requested IDs ?
  176. if (!lpdwAttrIDs || (*i)->dwId == *lpdwAttrIDs)
  177. {
  178. if (next)
  179. {
  180. if (next == stop)
  181. {
  182. *lpdwPosCount = count;
  183. return HRESULT_FROM_WIN32(ERROR_MORE_DATA);
  184. }
  185. IASAttributeAddRef(next->pAttribute = *i);
  186. ++next;
  187. }
  188. ++count;
  189. }
  190. }
  191. }
  192. *lpdwPosCount = count;
  193. return hr;
  194. }
  195. STDMETHODIMP Request::InsertBefore(
  196. PATTRIBUTEPOSITION newAttr,
  197. PATTRIBUTEPOSITION refAttr
  198. )
  199. {
  200. // Reserve space for the new attribute.
  201. if (!reserve(size() + 1))
  202. {
  203. return E_OUTOFMEMORY;
  204. }
  205. // Find the position; if it doesn't exist we'll do a simple add.
  206. PIASATTRIBUTE* pos = find(refAttr->pAttribute);
  207. if (pos == 0)
  208. {
  209. return AddAttributes(1, newAttr);
  210. }
  211. // Move the existing attribute out of the way.
  212. memmove(pos + 1, pos, (end - pos) * sizeof(PIASATTRIBUTE));
  213. ++end;
  214. // Store the new attribute.
  215. *pos = newAttr->pAttribute;
  216. IASAttributeAddRef(*pos);
  217. return S_OK;
  218. }
  219. STDMETHODIMP Request::Push(
  220. ULONG64 State
  221. )
  222. {
  223. const PULONG64 END_STATE = state + sizeof(state)/sizeof(state[0]);
  224. if (topOfStack != END_STATE)
  225. {
  226. *topOfStack = State;
  227. ++topOfStack;
  228. return S_OK;
  229. }
  230. return E_OUTOFMEMORY;
  231. }
  232. STDMETHODIMP Request::Pop(
  233. ULONG64* pState
  234. )
  235. {
  236. if (topOfStack != state)
  237. {
  238. --topOfStack;
  239. *pState = *topOfStack;
  240. return S_OK;
  241. }
  242. return E_FAIL;
  243. }
  244. STDMETHODIMP Request::Top(
  245. ULONG64* pState
  246. )
  247. {
  248. if (topOfStack != state)
  249. {
  250. *pState = *(topOfStack - 1);
  251. return S_OK;
  252. }
  253. return E_FAIL;
  254. }
  255. Request::Request() throw ()
  256. : source(NULL),
  257. protocol(IAS_PROTOCOL_RADIUS),
  258. request(IAS_REQUEST_ACCESS_REQUEST),
  259. response(IAS_RESPONSE_INVALID),
  260. reason(IAS_SUCCESS),
  261. begin(NULL),
  262. end(NULL),
  263. capacity(NULL),
  264. topOfStack(&state[0])
  265. {
  266. topOfStack = state;
  267. }
  268. Request::~Request() throw ()
  269. {
  270. for (PIASATTRIBUTE* i = begin; i != end; ++i)
  271. {
  272. IASAttributeRelease(*i);
  273. }
  274. delete[] begin;
  275. if (source) { source->Release(); }
  276. }
  277. inline size_t Request::size() const throw ()
  278. {
  279. return end - begin;
  280. }
  281. bool Request::reserve(size_t newCapacity) throw ()
  282. {
  283. if (newCapacity <= capacity)
  284. {
  285. return true;
  286. }
  287. // Increase the capacity by at least 50% and never less than 32.
  288. size_t minCapacity = (capacity > 21) ? (capacity * 3 / 2): 32;
  289. // Is the requested capacity less than the minimum resize?
  290. if (newCapacity < minCapacity)
  291. {
  292. newCapacity = minCapacity;
  293. }
  294. // Allocate the new array.
  295. PIASATTRIBUTE* newArray = new (std::nothrow) PIASATTRIBUTE[newCapacity];
  296. if (newArray == 0)
  297. {
  298. return false;
  299. }
  300. // Save the values in the old array.
  301. memcpy(newArray, begin, size() * sizeof(PIASATTRIBUTE));
  302. // Delete the old array.
  303. delete[] begin;
  304. // Update our pointers.
  305. end = newArray + size();
  306. begin = newArray;
  307. capacity = newCapacity;
  308. return true;
  309. }
  310. PIASATTRIBUTE* Request::find(IASATTRIBUTE* key) const throw ()
  311. {
  312. for (PIASATTRIBUTE* i = begin; i != end; ++i)
  313. {
  314. if (*i == key)
  315. {
  316. return i;
  317. }
  318. }
  319. return 0;
  320. }