Source code of Windows XP (NT5)
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.

344 lines
7.0 KiB

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