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.

914 lines
22 KiB

  1. ///////////////////////////////////////////////////////////////////////////////
  2. //
  3. // Copyright (c) Microsoft Corporation.
  4. //
  5. // SYNOPSIS
  6. //
  7. // Provides function definitions for the Internet Authentication Service
  8. // Template Library (IASTL).
  9. //
  10. ///////////////////////////////////////////////////////////////////////////////
  11. //////////
  12. // IASTL must be used in conjuction with ATL.
  13. //////////
  14. #ifndef __ATLCOM_H__
  15. #error iastlimp.cpp requires atlcom.h to be included first
  16. #endif
  17. #include <windows.h>
  18. //////////
  19. // IASTL declarations.
  20. //////////
  21. #include <iastl.h>
  22. //////////
  23. // The entire library is contained within the IASTL namespace.
  24. //////////
  25. namespace IASTL {
  26. //////////
  27. // FSM governing IAS components.
  28. //////////
  29. const IASComponent::State IASComponent::fsm[NUM_EVENTS][NUM_STATES] =
  30. {
  31. { STATE_UNINITIALIZED, STATE_UNEXPECTED, STATE_UNEXPECTED, STATE_UNEXPECTED },
  32. { STATE_UNEXPECTED, STATE_INITIALIZED, STATE_INITIALIZED, STATE_UNEXPECTED },
  33. { STATE_UNEXPECTED, STATE_UNEXPECTED, STATE_SUSPENDED, STATE_SUSPENDED },
  34. { STATE_UNEXPECTED, STATE_UNEXPECTED, STATE_INITIALIZED, STATE_INITIALIZED },
  35. { STATE_SHUTDOWN, STATE_SHUTDOWN, STATE_UNEXPECTED, STATE_SHUTDOWN }
  36. };
  37. ///////////////////////////////////////////////////////////////////////////////
  38. //
  39. // IASComponent
  40. //
  41. ///////////////////////////////////////////////////////////////////////////////
  42. HRESULT IASComponent::fireEvent(Event event) throw ()
  43. {
  44. // Check the input parameters.
  45. if (event >= NUM_EVENTS) { return E_UNEXPECTED; }
  46. // Compute the next state.
  47. State next = fsm[event][state];
  48. Lock();
  49. HRESULT hr;
  50. if (next == state)
  51. {
  52. // If we're already in that state, there's nothing to do.
  53. hr = S_OK;
  54. }
  55. else if (next == STATE_UNEXPECTED)
  56. {
  57. // We received an unexpected event.
  58. hr = E_UNEXPECTED;
  59. }
  60. else
  61. {
  62. // Attempt the transition.
  63. hr = attemptTransition(event);
  64. // Only change state if the transition was successful.
  65. if (SUCCEEDED(hr))
  66. {
  67. state = next;
  68. }
  69. }
  70. Unlock();
  71. return hr;
  72. }
  73. ///////////////////////////////////////////////////////////////////////////////
  74. //
  75. // IASRequestHandler
  76. //
  77. ///////////////////////////////////////////////////////////////////////////////
  78. STDMETHODIMP IASRequestHandler::OnRequest(IRequest* pRequest)
  79. {
  80. if (getState() != IASComponent::STATE_INITIALIZED)
  81. {
  82. pRequest->SetResponse(IAS_RESPONSE_DISCARD_PACKET, IAS_INTERNAL_ERROR);
  83. pRequest->ReturnToSource(IAS_REQUEST_STATUS_ABORT);
  84. }
  85. else
  86. {
  87. onAsyncRequest(pRequest);
  88. }
  89. return S_OK;
  90. }
  91. ///////////////////////////////////////////////////////////////////////////////
  92. //
  93. // IASRequestHandlerSync
  94. //
  95. ///////////////////////////////////////////////////////////////////////////////
  96. void IASRequestHandlerSync::onAsyncRequest(IRequest* pRequest) throw ()
  97. {
  98. pRequest->ReturnToSource(onSyncRequest(pRequest));
  99. }
  100. //////////
  101. // End of the IASTL namespace.
  102. //////////
  103. }
  104. //////////
  105. // Only pull in the utility classes if necessary.
  106. //////////
  107. #ifdef IASTLUTL_H
  108. //////////
  109. // The utility classes are also contained within the IASTL namespace.
  110. //////////
  111. namespace IASTL {
  112. ///////////////////////////////////////////////////////////////////////////////
  113. //
  114. // IASAttribute
  115. //
  116. ///////////////////////////////////////////////////////////////////////////////
  117. IASAttribute& IASAttribute::operator=(PIASATTRIBUTE attr) throw ()
  118. {
  119. // Check for self-assignment.
  120. if (p != attr)
  121. {
  122. _release();
  123. p = attr;
  124. _addref();
  125. }
  126. return *this;
  127. }
  128. void IASAttribute::attach(PIASATTRIBUTE attr, bool addRef) throw ()
  129. {
  130. _release();
  131. p = attr;
  132. if (addRef) { _addref(); }
  133. }
  134. bool IASAttribute::load(IAttributesRaw* request, DWORD dwId)
  135. {
  136. // Release any existing attribute.
  137. release();
  138. DWORD posCount = 1;
  139. ATTRIBUTEPOSITION pos;
  140. HRESULT hr = request->GetAttributes(&posCount, &pos, 1, &dwId);
  141. if (FAILED(hr))
  142. {
  143. if (hr == HRESULT_FROM_WIN32(ERROR_MORE_DATA))
  144. {
  145. // There was more than one, so release the partial result.
  146. IASAttributeRelease(pos.pAttribute);
  147. }
  148. issue_error(hr);
  149. }
  150. p = (posCount ? pos.pAttribute : NULL);
  151. return p != NULL;
  152. }
  153. bool IASAttribute::load(IAttributesRaw* request, DWORD dwId, IASTYPE itType)
  154. {
  155. // Get an attribute with the given ID.
  156. load(request, dwId);
  157. // Attributes have a fixed type, so if the type doesn't match it must
  158. // be an error.
  159. if (p && p->Value.itType != itType)
  160. {
  161. release();
  162. issue_error(DISP_E_TYPEMISMATCH);
  163. }
  164. return p != NULL;
  165. }
  166. void IASAttribute::store(IAttributesRaw* request) const
  167. {
  168. if (p)
  169. {
  170. ATTRIBUTEPOSITION pos;
  171. pos.pAttribute = p;
  172. HRESULT hr = request->AddAttributes(1, &pos);
  173. if (FAILED(hr))
  174. {
  175. issue_error(hr);
  176. }
  177. }
  178. }
  179. void IASAttribute::setOctetString(DWORD dwLength, const BYTE* lpValue)
  180. {
  181. PBYTE newVal = NULL;
  182. if (dwLength)
  183. {
  184. // Allocate a buffer for the octet string ...
  185. newVal = (PBYTE)CoTaskMemAlloc(dwLength);
  186. if (!newVal) { issue_error(E_OUTOFMEMORY); }
  187. // ... and copy it in.
  188. if (lpValue != NULL)
  189. {
  190. memcpy(newVal, lpValue, dwLength);
  191. }
  192. }
  193. // Clear the old value.
  194. clearValue();
  195. // Store the new.
  196. p->Value.OctetString.lpValue = newVal;
  197. p->Value.OctetString.dwLength = dwLength;
  198. p->Value.itType = IASTYPE_OCTET_STRING;
  199. }
  200. void IASAttribute::setOctetString(PCSTR szAnsi)
  201. {
  202. setOctetString((szAnsi ? strlen(szAnsi) : 0), (const BYTE*)szAnsi);
  203. }
  204. void IASAttribute::setOctetString(PCWSTR szWide)
  205. {
  206. // Allocate a buffer for the conversion.
  207. int len = WideCharToMultiByte(CP_ACP, 0, szWide, -1, NULL, 0, NULL, NULL);
  208. PSTR ansi = (PSTR)_alloca(len);
  209. // Convert from wide to ansi.
  210. len = WideCharToMultiByte(CP_ACP, 0, szWide, -1, ansi, len, NULL, NULL);
  211. // Don't include the null-terminator.
  212. if (len) { --len; }
  213. // Set the octet string.
  214. setOctetString(len, (const BYTE*)ansi);
  215. }
  216. void IASAttribute::setString(DWORD dwLength, const BYTE* lpValue)
  217. {
  218. // Reserve space for a null terminator.
  219. LPSTR newVal = (LPSTR)CoTaskMemAlloc(dwLength + 1);
  220. if (!newVal) { issue_error(E_OUTOFMEMORY); }
  221. // Copy in the string ...
  222. memcpy(newVal, lpValue, dwLength);
  223. // ... and add a null terminator.
  224. newVal[dwLength] = 0;
  225. // Clear the old value.
  226. clearValue();
  227. // Store the new value.
  228. p->Value.String.pszAnsi = newVal;
  229. p->Value.String.pszWide = NULL;
  230. p->Value.itType = IASTYPE_STRING;
  231. }
  232. void IASAttribute::setString(PCSTR szAnsi)
  233. {
  234. LPSTR newVal = NULL;
  235. if (szAnsi)
  236. {
  237. // Allocate a buffer for the string ...
  238. size_t nbyte = strlen(szAnsi) + 1;
  239. newVal = (LPSTR)CoTaskMemAlloc(nbyte);
  240. if (!newVal) { issue_error(E_OUTOFMEMORY); }
  241. // ... and copy it in.
  242. memcpy(newVal, szAnsi, nbyte);
  243. }
  244. // Clear the old value.
  245. clearValue();
  246. // Store the new value.
  247. p->Value.String.pszAnsi = newVal;
  248. p->Value.String.pszWide = NULL;
  249. p->Value.itType = IASTYPE_STRING;
  250. }
  251. void IASAttribute::setString(PCWSTR szWide)
  252. {
  253. LPWSTR newVal = NULL;
  254. if (szWide)
  255. {
  256. // Allocate a buffer for the string ...
  257. size_t nbyte = sizeof(WCHAR) * (wcslen(szWide) + 1);
  258. newVal = (LPWSTR)CoTaskMemAlloc(nbyte);
  259. if (!newVal) { issue_error(E_OUTOFMEMORY); }
  260. // ... and copy it in.
  261. memcpy(newVal, szWide, nbyte);
  262. }
  263. // Clear the old value.
  264. clearValue();
  265. // Store the new value.
  266. p->Value.String.pszWide = newVal;
  267. p->Value.String.pszAnsi = NULL;
  268. p->Value.itType = IASTYPE_STRING;
  269. }
  270. void IASAttribute::clearValue() throw ()
  271. {
  272. switch (p->Value.itType)
  273. {
  274. case IASTYPE_STRING:
  275. CoTaskMemFree(p->Value.String.pszAnsi);
  276. CoTaskMemFree(p->Value.String.pszWide);
  277. break;
  278. case IASTYPE_OCTET_STRING:
  279. CoTaskMemFree(p->Value.OctetString.lpValue);
  280. break;
  281. }
  282. p->Value.itType = IASTYPE_INVALID;
  283. }
  284. ///////////////////////////////////////////////////////////////////////////////
  285. //
  286. // IASAttributePosition
  287. //
  288. ///////////////////////////////////////////////////////////////////////////////
  289. IASAttributePosition& IASAttributePosition::operator=(
  290. const ATTRIBUTEPOSITION& rhs
  291. ) throw ()
  292. {
  293. operator=(rhs.pAttribute);
  294. pos.dwReserved = rhs.dwReserved;
  295. return *this;
  296. }
  297. IASAttributePosition& IASAttributePosition::operator=(
  298. IASATTRIBUTE* rhs
  299. ) throw ()
  300. {
  301. if (rhs != getAttribute())
  302. {
  303. _release();
  304. pos.pAttribute = rhs;
  305. _addref();
  306. }
  307. return *this;
  308. }
  309. ///////////////////////////////////////////////////////////////////////////////
  310. //
  311. // IASAttributeVector
  312. //
  313. ///////////////////////////////////////////////////////////////////////////////
  314. IASAttributeVector::IASAttributeVector() throw ()
  315. : begin_(NULL), end_(NULL), capacity_(0), owner(false)
  316. { }
  317. IASAttributeVector::IASAttributeVector(size_type N)
  318. : begin_(NULL), end_(NULL), capacity_(0), owner(false)
  319. {
  320. reserve(N);
  321. }
  322. IASAttributeVector::IASAttributeVector(
  323. PATTRIBUTEPOSITION init,
  324. size_type initCap
  325. ) throw ()
  326. : begin_(init), end_(begin_), capacity_(initCap), owner(false)
  327. { }
  328. IASAttributeVector::IASAttributeVector(const IASAttributeVector& v)
  329. : begin_(NULL), end_(NULL), capacity_(0), owner(false)
  330. {
  331. reserve(v.size());
  332. for (const_iterator i = v.begin(); i != v.end(); ++i, ++end_)
  333. {
  334. *end_ = *i;
  335. IASAttributeAddRef(end_->pAttribute);
  336. }
  337. }
  338. IASAttributeVector& IASAttributeVector::operator=(const IASAttributeVector& v)
  339. {
  340. if (this != &v)
  341. {
  342. clear();
  343. reserve(v.size());
  344. for (const_iterator i = v.begin(); i != v.end(); ++i, ++end_)
  345. {
  346. *end_ = *i;
  347. IASAttributeAddRef(end_->pAttribute);
  348. }
  349. }
  350. return *this;
  351. }
  352. IASAttributeVector::~IASAttributeVector() throw ()
  353. {
  354. clear();
  355. if (owner && begin_)
  356. {
  357. CoTaskMemFree(begin_);
  358. }
  359. }
  360. bool IASAttributeVector::contains(DWORD attrID) const throw ()
  361. {
  362. for (const_iterator i = begin(); i != end(); ++i)
  363. {
  364. if ((i->pAttribute != 0) && (i->pAttribute->dwId == attrID))
  365. {
  366. return true;
  367. }
  368. }
  369. return false;
  370. }
  371. IASAttributeVector::iterator IASAttributeVector::discard(iterator p) throw ()
  372. {
  373. // We now have one less attribute.
  374. --end_;
  375. // Shift over one.
  376. memmove(p, p + 1, (size_t)((PBYTE)end_ - (PBYTE)p));
  377. // The iterator now points to the next element, so no need to update.
  378. return p;
  379. }
  380. IASAttributeVector::iterator IASAttributeVector::fast_discard(iterator p) throw ()
  381. {
  382. // We now have one less attribute.
  383. --end_;
  384. // Use the attribute from the end to fill the empty slot.
  385. *p = *end_;
  386. return p;
  387. }
  388. DWORD IASAttributeVector::load(
  389. IAttributesRaw* request,
  390. DWORD attrIDCount,
  391. LPDWORD attrIDs
  392. )
  393. {
  394. clear();
  395. // Get the desired attributes.
  396. DWORD posCount = capacity_;
  397. HRESULT hr = request->GetAttributes(&posCount,
  398. begin_,
  399. attrIDCount,
  400. attrIDs);
  401. end_ = begin_ + posCount;
  402. if (FAILED(hr))
  403. {
  404. // Maybe the array just wasn't big enough.
  405. if (hr == HRESULT_FROM_WIN32(ERROR_MORE_DATA))
  406. {
  407. // Clear the partial result.
  408. clear();
  409. // Find out how much space we really need.
  410. DWORD needed = 0;
  411. hr = request->GetAttributes(&needed, NULL, attrIDCount, attrIDs);
  412. if (FAILED(hr)) { issue_error(hr); }
  413. // Reserve the necessary space ...
  414. reserve(needed);
  415. // ... and try again.
  416. return load(request, attrIDCount, attrIDs);
  417. }
  418. end_ = begin_;
  419. issue_error(hr);
  420. }
  421. return posCount;
  422. }
  423. DWORD IASAttributeVector::load(IAttributesRaw* request)
  424. {
  425. // Find out how much space we need.
  426. DWORD needed;
  427. HRESULT hr = request->GetAttributeCount(&needed);
  428. if (FAILED(hr)) { issue_error(hr); }
  429. // Make sure we have enough space.
  430. reserve(needed);
  431. return load(request, 0, NULL);
  432. }
  433. void IASAttributeVector::push_back(ATTRIBUTEPOSITION& p, bool addRef) throw ()
  434. {
  435. // Make sure we have enough room for one more attribute.
  436. if (size() == capacity())
  437. {
  438. reserve(empty() ? 1 : 2 * size());
  439. }
  440. if (addRef) { IASAttributeAddRef(p.pAttribute); }
  441. // Store the attribute at the end.
  442. *end_ = p;
  443. // Move the end.
  444. ++end_;
  445. }
  446. void IASAttributeVector::remove(IAttributesRaw* request)
  447. {
  448. if (begin_ != end_)
  449. {
  450. HRESULT hr = request->RemoveAttributes(size(), begin_);
  451. if (FAILED(hr)) { issue_error(hr); }
  452. }
  453. }
  454. void IASAttributeVector::store(IAttributesRaw* request) const
  455. {
  456. if (begin_ != end_)
  457. {
  458. HRESULT hr = request->AddAttributes(size(), begin_);
  459. if (FAILED(hr)) { issue_error(hr); }
  460. }
  461. }
  462. void IASAttributeVector::clear() throw ()
  463. {
  464. while (end_ != begin_)
  465. {
  466. --end_;
  467. IASAttributeRelease(end_->pAttribute);
  468. }
  469. }
  470. void IASAttributeVector::reserve(size_type N)
  471. {
  472. // We only worry about growing; shrinking is a nop.
  473. if (N > capacity_)
  474. {
  475. // Allocate memory for the new vector.
  476. PATTRIBUTEPOSITION tmp =
  477. (PATTRIBUTEPOSITION)CoTaskMemAlloc(N * sizeof(ATTRIBUTEPOSITION));
  478. if (tmp == NULL) { issue_error(E_OUTOFMEMORY); }
  479. // Copy the existing attributes into the new array.
  480. size_type size_ = size();
  481. memcpy(tmp, begin_, size_ * sizeof(ATTRIBUTEPOSITION));
  482. // Free the old array if necessary.
  483. if (owner) { CoTaskMemFree(begin_); }
  484. // Update our state to point at the new array.
  485. begin_ = tmp;
  486. end_ = begin_ + size_;
  487. capacity_ = N;
  488. owner = true;
  489. }
  490. }
  491. ///////////////////////////////////////////////////////////////////////////////
  492. //
  493. // IASRequest
  494. //
  495. ///////////////////////////////////////////////////////////////////////////////
  496. IASRequest::IASRequest(IRequest* request)
  497. : req(request)
  498. {
  499. if (!req)
  500. {
  501. // We don't allow NULL request objects.
  502. issue_error(E_POINTER);
  503. }
  504. // Get the 'raw' counterpart.
  505. checkError(req->QueryInterface(__uuidof(IAttributesRaw), (PVOID*)&raw));
  506. }
  507. IASRequest& IASRequest::operator=(const IASRequest& request) throw ()
  508. {
  509. // Check for self-assignment.
  510. if (this != &request)
  511. {
  512. _release();
  513. req = request.req;
  514. raw = request.raw;
  515. _addref();
  516. }
  517. return *this;
  518. }
  519. DWORD IASRequest::GetAttributes(DWORD dwPosCount,
  520. PATTRIBUTEPOSITION pPositions,
  521. DWORD dwAttrIDCount,
  522. LPDWORD lpdwAttrIDs)
  523. {
  524. DWORD count = dwPosCount;
  525. HRESULT hr = raw->GetAttributes(&count,
  526. pPositions,
  527. dwAttrIDCount,
  528. lpdwAttrIDs);
  529. if (FAILED(hr))
  530. {
  531. if (hr == HRESULT_FROM_WIN32(ERROR_MORE_DATA))
  532. {
  533. // Free the partial results.
  534. while (count--)
  535. {
  536. IASAttributeRelease(pPositions->pAttribute);
  537. pPositions->pAttribute = NULL;
  538. ++pPositions;
  539. }
  540. }
  541. issue_error(hr);
  542. }
  543. return count;
  544. }
  545. IASDictionary::IASDictionary(
  546. const WCHAR* const* selectNames,
  547. PCWSTR path
  548. )
  549. : mapSize(0),
  550. nextRowNumber(0),
  551. currentRow(NULL)
  552. {
  553. if (!path)
  554. {
  555. // No path, so get the cached local dictionary.
  556. table = IASGetLocalDictionary();
  557. if (!table) { issue_error(GetLastError()); }
  558. }
  559. else
  560. {
  561. // Otherwise, get an arbitrary dictionary.
  562. HRESULT hr = IASGetDictionary(path, &data, &storage);
  563. if (FAILED(hr)) { issue_error(hr); }
  564. table = &data;
  565. }
  566. // How many columns are selected ?
  567. for (const WCHAR* const* p = selectNames; *p; ++p)
  568. {
  569. ++mapSize;
  570. }
  571. // Allocate memory for the map.
  572. selectMap = (PULONG)CoTaskMemAlloc(mapSize * sizeof(ULONG));
  573. if (!selectMap) { issue_error(E_OUTOFMEMORY); }
  574. // Lookup the column names.
  575. for (ULONG i = 0; i < mapSize; ++i)
  576. {
  577. // If it begins with a '-', it's optional.
  578. bool optional = false;
  579. const wchar_t* name = selectNames[i];
  580. if (*name == L'-')
  581. {
  582. optional = true;
  583. ++name;
  584. }
  585. // Find the column number.
  586. ULONG columnNumber = 0;
  587. while ((columnNumber < table->numColumns) &&
  588. (_wcsicmp(name, table->columnNames[columnNumber]) != 0))
  589. {
  590. ++columnNumber;
  591. }
  592. if ((columnNumber == table->numColumns) && !optional)
  593. {
  594. // We didn't find the column.
  595. CoTaskMemFree(selectMap);
  596. issue_error(E_INVALIDARG);
  597. }
  598. selectMap[i] = columnNumber;
  599. }
  600. }
  601. IASDictionary::~IASDictionary() throw ()
  602. {
  603. CoTaskMemFree(selectMap);
  604. }
  605. bool IASDictionary::next() throw ()
  606. {
  607. // Are there any rows left ?
  608. if (nextRowNumber >= table->numRows) { return false; }
  609. // Set currentRow to the next row.
  610. currentRow = table->table + nextRowNumber * table->numColumns;
  611. // Advance nextRowNumber.
  612. ++nextRowNumber;
  613. return true;
  614. }
  615. void IASDictionary::reset() throw ()
  616. {
  617. nextRowNumber = 0;
  618. currentRow = NULL;
  619. }
  620. bool IASDictionary::isEmpty(ULONG ordinal) const
  621. {
  622. return V_VT(getVariant(ordinal)) == VT_EMPTY;
  623. }
  624. VARIANT_BOOL IASDictionary::getBool(ULONG ordinal) const
  625. {
  626. const VARIANT* v = getVariant(ordinal);
  627. if (V_VT(v) == VT_BOOL)
  628. {
  629. return V_BOOL(v);
  630. }
  631. else if (V_VT(v) != VT_EMPTY)
  632. {
  633. issue_error(DISP_E_TYPEMISMATCH);
  634. }
  635. return VARIANT_FALSE;
  636. }
  637. BSTR IASDictionary::getBSTR(ULONG ordinal) const
  638. {
  639. const VARIANT* v = getVariant(ordinal);
  640. if (V_VT(v) == VT_BSTR)
  641. {
  642. return V_BSTR(v);
  643. }
  644. else if (V_VT(v) != VT_EMPTY)
  645. {
  646. issue_error(DISP_E_TYPEMISMATCH);
  647. }
  648. return NULL;
  649. }
  650. LONG IASDictionary::getLong(ULONG ordinal) const
  651. {
  652. const VARIANT* v = getVariant(ordinal);
  653. if (V_VT(v) == VT_I4)
  654. {
  655. return V_I4(v);
  656. }
  657. else if (V_VT(v) != VT_EMPTY)
  658. {
  659. issue_error(DISP_E_TYPEMISMATCH);
  660. }
  661. return 0L;
  662. }
  663. const VARIANT* IASDictionary::getVariant(ULONG ordinal) const
  664. {
  665. static VARIANT empty;
  666. // Are we positioned on a row ?
  667. if (!currentRow) { issue_error(E_UNEXPECTED); }
  668. // Is the ordinal valid ?
  669. if (ordinal >= mapSize) { issue_error(E_INVALIDARG); }
  670. // Get the table column.
  671. ULONG column = selectMap[ordinal];
  672. // If it's out of range, this must have been an optional field, so return
  673. // an empty VARIANT.
  674. return (column >= table->numColumns) ? &empty : currentRow + column;
  675. }
  676. //////////
  677. // End of the IASTL namespace.
  678. //////////
  679. }
  680. ///////////////////////////////////////////////////////////////////////////////
  681. //
  682. // OctetString conversion macros and functions.
  683. //
  684. ///////////////////////////////////////////////////////////////////////////////
  685. PSTR IASOctetStringToAnsi(const IAS_OCTET_STRING& src, PSTR dst) throw ()
  686. {
  687. dst[src.dwLength] = '\0';
  688. return (PSTR)memcpy(dst, src.lpValue, src.dwLength);
  689. }
  690. PWSTR IASOctetStringToWide(const IAS_OCTET_STRING& src, PWSTR dst) throw ()
  691. {
  692. DWORD nChar = MultiByteToWideChar(CP_ACP,
  693. 0,
  694. (PSTR)src.lpValue,
  695. src.dwLength,
  696. dst,
  697. src.dwLength);
  698. dst[nChar] = L'\0';
  699. return dst;
  700. }
  701. ///////////////////////////////////////////////////////////////////////////////
  702. //
  703. // Miscellaneous functions.
  704. //
  705. ///////////////////////////////////////////////////////////////////////////////
  706. // Returns 'true' if the IASTYPE maps to a RADIUS integer attribute.
  707. bool isRadiusInteger(IASTYPE type) throw ()
  708. {
  709. bool retval;
  710. switch (type)
  711. {
  712. case IASTYPE_BOOLEAN:
  713. case IASTYPE_INTEGER:
  714. case IASTYPE_ENUM:
  715. retval = true;
  716. break;
  717. default:
  718. retval = false;
  719. }
  720. return retval;
  721. }
  722. PIASATTRIBUTE IASPeekAttribute(
  723. IAttributesRaw* request,
  724. DWORD dwId,
  725. IASTYPE itType
  726. ) throw ()
  727. {
  728. if (request)
  729. {
  730. DWORD posCount = 1;
  731. ATTRIBUTEPOSITION pos;
  732. HRESULT hr = request->GetAttributes(&posCount, &pos, 1, &dwId);
  733. if (posCount == 1)
  734. {
  735. IASAttributeRelease(pos.pAttribute);
  736. if (SUCCEEDED(hr))
  737. {
  738. // There is some confusion between RAS and IAS regarding which
  739. // IASTYPEs to use for various RADIUS attributes, so we'll assume
  740. // any of the RADIUS integer types are interchangeable.
  741. if (itType == pos.pAttribute->Value.itType ||
  742. (isRadiusInteger(itType) &&
  743. isRadiusInteger(pos.pAttribute->Value.itType)))
  744. {
  745. return pos.pAttribute;
  746. }
  747. }
  748. }
  749. }
  750. return NULL;
  751. }
  752. //////////
  753. // End of utility classe.
  754. //////////
  755. #endif // IASTLUTL_H