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.

879 lines
20 KiB

  1. //////////////////////////////////////////////////////////////////////////////
  2. /*++
  3. Copyright (C) Microsoft Corporation, 1998 - 1999
  4. Module Name:
  5. IASStringAttributeEditor.cpp
  6. Abstract:
  7. Implementation file for the CIASStringAttributeEditor class.
  8. Revision History:
  9. mmaguire 06/25/98 - created
  10. --*/
  11. //////////////////////////////////////////////////////////////////////////////
  12. //////////////////////////////////////////////////////////////////////////////
  13. // BEGIN INCLUDES
  14. //
  15. // standard includes:
  16. //
  17. #include "Precompiled.h"
  18. //
  19. // where we can find declaration for main class in this file:
  20. //
  21. #include "IASStringAttributeEditor.h"
  22. //
  23. // where we can find declarations needed in this file:
  24. //
  25. #include "IASStringEditorPage.h"
  26. #include "iashelper.h"
  27. //
  28. // END INCLUDES
  29. //////////////////////////////////////////////////////////////////////////////
  30. BYTE PREFIX___RADIUS_ATTRIBUTE_TUNNEL_PASSWORD[] = {0,0,0,0};
  31. UINT PREFIX_LEN___RADIUS_ATTRIBUTE_TUNNEL_PASSWORD = 4;
  32. UINT PREFIX_OFFSET_DATALENBYTE___RADIUS_ATTRIBUTE_TUNNEL_PASSWORD = 3; // 0 based index -- the fourth byte
  33. UINT PREFIX_LEN_DATALENBYTE___RADIUS_ATTRIBUTE_TUNNEL_PASSWORD = 1; // one byte
  34. //////////////////////////////////////////////////////////////////////////////
  35. /*++
  36. CIASStringAttributeEditor::ShowEditor
  37. --*/
  38. //////////////////////////////////////////////////////////////////////////////
  39. STDMETHODIMP CIASStringAttributeEditor::ShowEditor( /*[in, out]*/ BSTR *pReserved )
  40. {
  41. TRACE(_T("CIASStringAttributeEditor::ShowEditor\n"));
  42. AFX_MANAGE_STATE(AfxGetStaticModuleState())
  43. HRESULT hr = S_OK;
  44. try
  45. {
  46. // Load page title.
  47. // ::CString strPageTitle;
  48. // strPageTitle.LoadString(IDS_IAS_IP_EDITOR_TITLE);
  49. //
  50. // CPropertySheet propSheet( (LPCTSTR)strPageTitle );
  51. //
  52. // IP Address Editor
  53. //
  54. CIASPgSingleAttr cppPage;
  55. // Initialize the page's data exchange fields with info from IAttributeInfo
  56. CComBSTR bstrName;
  57. CComBSTR bstrSyntax;
  58. ATTRIBUTESYNTAX asSyntax = IAS_SYNTAX_OCTETSTRING;
  59. ATTRIBUTEID Id = ATTRIBUTE_UNDEFINED;
  60. if( m_spIASAttributeInfo )
  61. {
  62. hr = m_spIASAttributeInfo->get_AttributeName( &bstrName );
  63. if( FAILED(hr) ) throw hr;
  64. hr = m_spIASAttributeInfo->get_SyntaxString( &bstrSyntax );
  65. if( FAILED(hr) ) throw hr;
  66. hr = m_spIASAttributeInfo->get_AttributeSyntax( &asSyntax );
  67. if( FAILED(hr) ) throw hr;
  68. hr = m_spIASAttributeInfo->get_AttributeID( &Id );
  69. if( FAILED(hr) ) throw hr;
  70. }
  71. cppPage.m_strAttrName = bstrName;
  72. cppPage.m_AttrSyntax = asSyntax;
  73. cppPage.m_nAttrId = Id;
  74. cppPage.m_strAttrFormat = bstrSyntax;
  75. // Attribute type is actually attribute ID in string format
  76. WCHAR szTempId[MAX_PATH];
  77. wsprintf(szTempId, _T("%ld"), Id);
  78. cppPage.m_strAttrType = szTempId;
  79. // Initialize the page's data exchange fields with info from VARIANT value passed in.
  80. if ( V_VT(m_pvarValue) != VT_EMPTY )
  81. {
  82. EStringType sp;
  83. CComBSTR bstrTemp;
  84. get_ValueAsStringEx( &bstrTemp, &sp );
  85. cppPage.m_strAttrValue = bstrTemp;
  86. cppPage.m_OctetStringType = sp;
  87. }
  88. // propSheet.AddPage(&cppPage);
  89. // int iResult = propSheet.DoModal();
  90. int iResult = cppPage.DoModal();
  91. if (IDOK == iResult)
  92. {
  93. CComBSTR bstrTemp = (LPCTSTR)cppPage.m_strAttrValue;
  94. put_ValueAsStringEx( bstrTemp, cppPage.m_OctetStringType);
  95. }
  96. else
  97. {
  98. hr = S_FALSE;
  99. }
  100. //
  101. // delete the property page pointer
  102. //
  103. // propSheet.RemovePage(&cppPage);
  104. }
  105. catch( HRESULT & hr )
  106. {
  107. return hr;
  108. }
  109. catch(...)
  110. {
  111. return hr = E_FAIL;
  112. }
  113. return hr;
  114. }
  115. //////////////////////////////////////////////////////////////////////////////
  116. /*++
  117. CIASStringAttributeEditor::SetAttributeValue
  118. --*/
  119. //////////////////////////////////////////////////////////////////////////////
  120. STDMETHODIMP CIASStringAttributeEditor::SetAttributeValue(VARIANT * pValue)
  121. {
  122. TRACE(_T("CIASStringAttributeEditor::SetAttributeValue\n"));
  123. AFX_MANAGE_STATE(AfxGetStaticModuleState())
  124. // Check for preconditions.
  125. if( ! pValue )
  126. {
  127. return E_INVALIDARG;
  128. }
  129. // From Baogang's old code, it appears that this editor should accept
  130. // either VT_BSTR, VT_BOOL, VT_I4 or VT_EMPTY.
  131. if( V_VT(pValue) != VT_BSTR
  132. && V_VT(pValue) != VT_BOOL
  133. && V_VT(pValue) != VT_I4
  134. && V_VT(pValue) != VT_EMPTY
  135. && V_VT(pValue) != (VT_ARRAY | VT_UI1))
  136. {
  137. return E_INVALIDARG;
  138. }
  139. m_pvarValue = pValue;
  140. return S_OK;
  141. }
  142. //////////////////////////////////////////////////////////////////////////////
  143. /*++
  144. CIASStringAttributeEditor::get_ValueAsString
  145. --*/
  146. //////////////////////////////////////////////////////////////////////////////
  147. STDMETHODIMP CIASStringAttributeEditor::get_ValueAsString(BSTR * pbstrDisplayText )
  148. {
  149. TRACE(_T("CIASStringAttributeEditor::get_ValueAsString\n"));
  150. AFX_MANAGE_STATE(AfxGetStaticModuleState())
  151. // Check for preconditions.
  152. if( ! pbstrDisplayText )
  153. {
  154. return E_INVALIDARG;
  155. }
  156. if( ! m_spIASAttributeInfo || ! m_pvarValue )
  157. {
  158. // We are not initialized properly.
  159. return OLE_E_BLANK;
  160. }
  161. HRESULT hr = S_OK;
  162. try
  163. {
  164. CComBSTR bstrDisplay;
  165. VARTYPE vType = V_VT(m_pvarValue);
  166. switch( vType )
  167. {
  168. case VT_BOOL:
  169. {
  170. if( V_BOOL(m_pvarValue) )
  171. {
  172. // ISSUE: This is not localizable!!!
  173. // Should it be? Ask Ashwin about this as some of
  174. // Baogang's error checking code was specifically looking
  175. // for either hardcoded "TRUE" or "FALSE".
  176. // ISSUE: I think that for Boolean syntax attributes,
  177. // we should be popping up the same type of attribute
  178. // editor as for the enumerables only with TRUE and FALSE in it.
  179. bstrDisplay = L"TRUE";
  180. }
  181. else
  182. {
  183. bstrDisplay = L"FALSE";
  184. }
  185. }
  186. break;
  187. case VT_I4:
  188. {
  189. // The variant is some type which must be coerced to a bstr.
  190. CComVariant varValue;
  191. // Make sure you pass a VT_EMPTY variant to VariantChangeType
  192. // or it will assert.
  193. // So don't do: V_VT(&varValue) = VT_BSTR;
  194. hr = VariantChangeType(&varValue, m_pvarValue, VARIANT_NOVALUEPROP, VT_BSTR);
  195. if( FAILED( hr ) ) throw hr;
  196. bstrDisplay = V_BSTR(&varValue);
  197. }
  198. break;
  199. case VT_BSTR:
  200. bstrDisplay = V_BSTR(m_pvarValue);
  201. break;
  202. case VT_UI1 | VT_ARRAY: // Treat as Octet string
  203. {
  204. EStringType t;
  205. return get_ValueAsStringEx(pbstrDisplayText, &t);
  206. }
  207. break;
  208. default:
  209. // need to check what is happening here,
  210. ASSERT(0);
  211. break;
  212. case VT_EMPTY:
  213. // do nothing -- we will fall through and return a blank string.
  214. break;
  215. }
  216. *pbstrDisplayText = bstrDisplay.Copy();
  217. }
  218. catch( HRESULT &hr )
  219. {
  220. return hr;
  221. }
  222. catch(...)
  223. {
  224. return E_FAIL;
  225. }
  226. return hr;
  227. }
  228. //////////////////////////////////////////////////////////////////////////////
  229. /*++
  230. CIASStringAttributeEditor::put_ValueAsString
  231. --*/
  232. //////////////////////////////////////////////////////////////////////////////
  233. STDMETHODIMP CIASStringAttributeEditor::put_ValueAsString(BSTR newVal)
  234. {
  235. TRACE(_T("CIASStringAttributeEditor::put_ValueAsString\n"));
  236. AFX_MANAGE_STATE(AfxGetStaticModuleState())
  237. if( ! m_pvarValue )
  238. {
  239. // We are not initialized properly.
  240. return OLE_E_BLANK;
  241. }
  242. if( m_spIASAttributeInfo == NULL )
  243. {
  244. // We are not initialized properly.
  245. return OLE_E_BLANK;
  246. }
  247. HRESULT hr = S_OK;
  248. try
  249. {
  250. CComBSTR bstrTemp = newVal;
  251. CComVariant varValue;
  252. V_VT(&varValue) = VT_BSTR;
  253. V_BSTR(&varValue) = bstrTemp.Copy();
  254. VARTYPE vType = V_VT(m_pvarValue);
  255. // Initialize the variant that was passed in.
  256. VariantClear(m_pvarValue);
  257. {
  258. ATTRIBUTESYNTAX asSyntax;
  259. hr = m_spIASAttributeInfo->get_AttributeSyntax( &asSyntax );
  260. if( FAILED(hr) ) throw hr;
  261. // if this Octet string, this should be BSTR, no matter what it was before.
  262. if(asSyntax == IAS_SYNTAX_OCTETSTRING)
  263. vType = VT_BSTR;
  264. if ( VT_EMPTY == vType)
  265. {
  266. // decide the value type:
  267. switch (asSyntax)
  268. {
  269. case IAS_SYNTAX_BOOLEAN:
  270. vType = VT_BOOL;
  271. break;
  272. case IAS_SYNTAX_INTEGER:
  273. case IAS_SYNTAX_UNSIGNEDINTEGER:
  274. case IAS_SYNTAX_ENUMERATOR:
  275. case IAS_SYNTAX_INETADDR:
  276. vType = VT_I4;
  277. break;
  278. case IAS_SYNTAX_STRING:
  279. case IAS_SYNTAX_UTCTIME:
  280. case IAS_SYNTAX_PROVIDERSPECIFIC:
  281. case IAS_SYNTAX_OCTETSTRING:
  282. vType = VT_BSTR;
  283. break;
  284. default:
  285. _ASSERTE(FALSE);
  286. vType = VT_BSTR;
  287. break;
  288. }
  289. }
  290. }
  291. hr = VariantChangeType(m_pvarValue, &varValue, VARIANT_NOVALUEPROP, vType);
  292. if( FAILED( hr ) ) throw hr;
  293. }
  294. catch( HRESULT &hr )
  295. {
  296. return hr;
  297. }
  298. catch(...)
  299. {
  300. return E_FAIL;
  301. }
  302. return hr;
  303. }
  304. //////////////////////////////////////////////////////////////////////////////
  305. /*++
  306. CIASStringAttributeEditor::get_ValueAsStringEx
  307. --*/
  308. //////////////////////////////////////////////////////////////////////////////
  309. STDMETHODIMP CIASStringAttributeEditor::get_ValueAsStringEx(BSTR * pbstrDisplayText, EStringType* pType )
  310. {
  311. TRACE(_T("CIASStringAttributeEditor::get_ValueAsString\n"));
  312. AFX_MANAGE_STATE(AfxGetStaticModuleState())
  313. ATTRIBUTESYNTAX asSyntax;
  314. m_spIASAttributeInfo->get_AttributeSyntax( &asSyntax );
  315. if(asSyntax != IAS_SYNTAX_OCTETSTRING)
  316. {
  317. if(pType)
  318. *pType = STRING_TYPE_NORMAL;
  319. return get_ValueAsString(pbstrDisplayText);
  320. }
  321. // only care about IAS_SYNTAX_OCTETSTRING
  322. ASSERT(pType);
  323. VARTYPE vType = V_VT(m_pvarValue);
  324. SAFEARRAY* psa = NULL;
  325. HRESULT hr = S_OK;
  326. switch(vType)
  327. {
  328. case VT_ARRAY | VT_UI1:
  329. psa = V_ARRAY(m_pvarValue);
  330. break;
  331. case VT_EMPTY:
  332. if(pType)
  333. *pType = STRING_TYPE_NULL;
  334. return get_ValueAsString(pbstrDisplayText);
  335. break;
  336. case VT_BSTR:
  337. if(pType)
  338. *pType = STRING_TYPE_NORMAL;
  339. return get_ValueAsString(pbstrDisplayText);
  340. break;
  341. default:
  342. ASSERT(0); // should not happen, should correct some code
  343. if(pType)
  344. *pType = STRING_TYPE_NORMAL;
  345. return get_ValueAsString(pbstrDisplayText);
  346. break;
  347. };
  348. // no data is available , or the safe array is not valid, don't intepret the string
  349. if(psa == NULL || psa->cDims != 1 || psa->cbElements != 1)
  350. {
  351. *pType = STRING_TYPE_NULL;
  352. return hr;
  353. }
  354. // need to figure out how to convert the binary to text
  355. char* pData = NULL;
  356. int nBytes = 0;
  357. WCHAR* pWStr = NULL;
  358. int nWStr = 0;
  359. DWORD dwErr = 0;
  360. BOOL bStringConverted = FALSE;
  361. CComBSTR bstrDisplay;
  362. EStringType sType = STRING_TYPE_NULL;
  363. hr = ::SafeArrayAccessData( psa, (void**)&pData);
  364. if(hr != S_OK)
  365. return hr;
  366. nBytes = psa->rgsabound[0].cElements;
  367. ASSERT(pData);
  368. if(!pData) goto Error;
  369. #ifdef __WE_WANT_TO_USE_UTF8_FOR_NORMAL_STRING_AS_WELL_
  370. // UTF8 requires the flag to be 0
  371. nWStr = MultiByteToWideChar(CP_UTF8, 0, pData, nBytes, NULL, 0);
  372. if(nWStr == 0)
  373. dwErr = GetLastError();
  374. #endif
  375. try{
  376. #ifdef __WE_WANT_TO_USE_UTF8_FOR_NORMAL_STRING_AS_WELL_
  377. if(nWStr != 0) // succ
  378. {
  379. pWStr = new WCHAR[nWStr + 2]; // for the 2 "s
  380. int i = 0;
  381. nWStr == MultiByteToWideChar(CP_UTF8, 0, pData, nBytes, pWStr , nWStr);
  382. // if every char is printable
  383. for(i = 0; i < nWStr -1; i++)
  384. {
  385. if(iswprint(pWStr[i]) == 0)
  386. break;
  387. }
  388. if(0 == nWStr || i != nWStr - 1 || pWStr[i] != L'\0')
  389. {
  390. delete[] pWStr;
  391. pWStr = NULL;
  392. }
  393. else
  394. {
  395. // added quotes
  396. memmove(pWStr + 1, pWStr, nWStr * sizeof(WCHAR));
  397. pWStr[0] = L'"';
  398. pWStr[nWStr] = L'"';
  399. pWStr[nWStr + 1 ] = 0; // new end of string
  400. bStringConverted = TRUE; // to prevent from furthe convertion to HEX
  401. sType = STRING_TYPE_UNICODE;
  402. }
  403. }
  404. #endif // __WE_WANT_TO_USE_UTF8_FOR_NORMAL_STRING_AS_WELL_
  405. // check if the attriabute is RADIUS_ATTRIBUTE_TUNNEL_PASSWORD,
  406. // this attribute has special format --- remove 0's from the binary and
  407. // try to conver to text
  408. {
  409. ATTRIBUTEID Id;
  410. hr = m_spIASAttributeInfo->get_AttributeID( &Id );
  411. if( FAILED(hr) ) goto Error;
  412. if ( Id == RADIUS_ATTRIBUTE_TUNNEL_PASSWORD)
  413. {
  414. //BYTE PREFIX___RADIUS_ATTRIBUTE_TUNNEL_PASSWORD[] = {0,0,0,0};
  415. //UINT PREFIX_LEN___RADIUS_ATTRIBUTE_TUNNEL_PASSWORD = 4;
  416. //UINT PREFIX_OFFSET_DATALENBYTE___RADIUS_ATTRIBUTE_TUNNEL_PASSWORD = 3; // 0 based index -- the fourth byte
  417. //UINT PREFIX_LEN_DATALENBYTE___RADIUS_ATTRIBUTE_TUNNEL_PASSWORD = 1
  418. if(PREFIX_LEN___RADIUS_ATTRIBUTE_TUNNEL_PASSWORD <=nBytes &&
  419. memcmp(pData,
  420. PREFIX___RADIUS_ATTRIBUTE_TUNNEL_PASSWORD,
  421. PREFIX_LEN___RADIUS_ATTRIBUTE_TUNNEL_PASSWORD - PREFIX_LEN_DATALENBYTE___RADIUS_ATTRIBUTE_TUNNEL_PASSWORD) == 0)
  422. {
  423. // correct prefix,
  424. // remove the prefix
  425. pData += PREFIX_LEN___RADIUS_ATTRIBUTE_TUNNEL_PASSWORD;
  426. nBytes -= PREFIX_LEN___RADIUS_ATTRIBUTE_TUNNEL_PASSWORD;
  427. // try to convert to UNICODE TEXT using CP_ACP -- get length
  428. nWStr = MultiByteToWideChar(CP_ACP, MB_ERR_INVALID_CHARS, pData, nBytes, NULL, 0);
  429. if(nWStr != 0) // which means, we can not convert
  430. {
  431. pWStr = new WCHAR[nWStr + 1];
  432. // try to convert to UNICODE TEXT using CP_ACP
  433. nWStr = MultiByteToWideChar(CP_ACP, MB_ERR_INVALID_CHARS, pData, nBytes, pWStr, nWStr);
  434. if(nWStr != 0)
  435. {
  436. int i = 0;
  437. for(i = 0; i < nWStr; i++)
  438. {
  439. if(iswprint(pWStr[i]) == 0)
  440. break;
  441. }
  442. if( i == nWStr) // all printable
  443. {
  444. bStringConverted = TRUE;
  445. pWStr[nWStr] = 0; // NULL terminator
  446. }
  447. }
  448. if (!bStringConverted) // undo the thing
  449. {
  450. // release the buffer
  451. delete[] pWStr;
  452. pWStr = NULL;
  453. nWStr = 0;
  454. }
  455. }
  456. }
  457. }
  458. }
  459. if(!bStringConverted) // not converted above, convert to HEX string
  460. {
  461. nWStr = BinaryToHexString(pData, nBytes, NULL, 0); // find out the size of the buffer
  462. pWStr = new WCHAR[nWStr];
  463. ASSERT(pWStr); // should have thrown if there is not enough memory
  464. BinaryToHexString(pData, nBytes, pWStr, nWStr);
  465. bStringConverted = TRUE; // to prevent from furthe convertion to HEX
  466. sType = STRING_TYPE_HEX_FROM_BINARY;
  467. }
  468. if(bStringConverted)
  469. {
  470. bstrDisplay = pWStr;
  471. // fill in the output parameters
  472. *pbstrDisplayText = bstrDisplay.Copy();
  473. *pType = sType;
  474. delete[] pWStr;
  475. pWStr = NULL;
  476. }
  477. }
  478. catch(...)
  479. {
  480. hr = E_OUTOFMEMORY;
  481. goto Error;
  482. }
  483. Error:
  484. if(pWStr)
  485. delete[] pWStr;
  486. if(psa)
  487. ::SafeArrayUnaccessData(psa);
  488. return hr;
  489. }
  490. //////////////////////////////////////////////////////////////////////////////
  491. /*++
  492. */
  493. //////////////////////////////////////////////////////////////////////////////
  494. /*++
  495. CIASStringAttributeEditor::put_ValueAsStringEx
  496. --*/
  497. //////////////////////////////////////////////////////////////////////////////
  498. STDMETHODIMP CIASStringAttributeEditor::put_ValueAsStringEx(BSTR newVal, EStringType type)
  499. {
  500. TRACE(_T("CIASStringAttributeEditor::put_ValueAsStringEx\n"));
  501. AFX_MANAGE_STATE(AfxGetStaticModuleState())
  502. ATTRIBUTESYNTAX asSyntax;
  503. m_spIASAttributeInfo->get_AttributeSyntax( &asSyntax );
  504. if(asSyntax != IAS_SYNTAX_OCTETSTRING)
  505. return put_ValueAsString(newVal);
  506. // only care about IAS_SYNTAX_OCTETSTRING
  507. HRESULT hr = S_OK;
  508. char* pData = NULL;
  509. int nLen = 0;
  510. switch(type)
  511. {
  512. case STRING_TYPE_NULL:
  513. // remove the data
  514. break;
  515. case STRING_TYPE_NORMAL:
  516. case STRING_TYPE_UNICODE:
  517. #ifdef __WE_WANT_TO_USE_UTF8_FOR_NORMAL_STRING_AS_WELL_
  518. // need to convert UTF8 before passing into SafeArray
  519. nLen = WideCharToMultiByte(CP_UTF8, 0, newVal, -1, NULL, 0, NULL, NULL);
  520. if(nLen != 0) // when == 0 , need not to do anything
  521. {
  522. try{
  523. pData = new char[nLen];
  524. nLen = WideCharToMultiByte(CP_UTF8, 0, newVal, -1, pData, nLen, NULL, NULL);
  525. }
  526. catch(...)
  527. {
  528. hr = E_OUTOFMEMORY;
  529. goto Error;
  530. }
  531. }
  532. break;
  533. #else
  534. // check if the attriabute is RADIUS_ATTRIBUTE_TUNNEL_PASSWORD,
  535. // this attribute has special format --- remove 0's from the binary and
  536. // try to conver to text
  537. {
  538. ATTRIBUTEID Id;
  539. hr = m_spIASAttributeInfo->get_AttributeID( &Id );
  540. if( FAILED(hr) ) goto Error;
  541. if ( Id == RADIUS_ATTRIBUTE_TUNNEL_PASSWORD)
  542. {
  543. BOOL bUsedDefault = FALSE;
  544. UINT nStrLen = wcslen(newVal);
  545. // try to convert to UNICODE TEXT using CP_ACP -- get length
  546. nLen = ::WideCharToMultiByte(CP_ACP, 0, newVal, nStrLen, NULL, 0, NULL, &bUsedDefault);
  547. if(nLen != 0) // which means, we can not convert
  548. {
  549. try{
  550. pData = new char[nLen];
  551. ASSERT(pData);
  552. // try to convert to UNICODE TEXT using CP_ACP
  553. nLen = ::WideCharToMultiByte(CP_ACP, 0, newVal, nStrLen, pData, nLen, NULL, &bUsedDefault);
  554. }
  555. catch(...)
  556. {
  557. hr = E_OUTOFMEMORY;
  558. goto Error;
  559. }
  560. }
  561. if(nLen == 0 || bUsedDefault) // failed to convert, then error message
  562. {
  563. // ANSI code page is allowed
  564. hr = E_INVALIDARG;
  565. AfxMessageBox(IDS_IAS_ERR_INVALIDCHARINPASSWORD);
  566. goto Error;
  567. }
  568. }
  569. else
  570. return put_ValueAsString(newVal);
  571. }
  572. break;
  573. #endif
  574. case STRING_TYPE_HEX_FROM_BINARY:
  575. // need to convert to binary before passing into SafeArray
  576. if(wcslen(newVal) != 0)
  577. {
  578. newVal = GetValidVSAHexString(newVal);
  579. if(newVal == NULL)
  580. {
  581. hr = E_INVALIDARG;
  582. goto Error;
  583. }
  584. nLen = HexStringToBinary(newVal, NULL, 0); // find out the size of the buffer
  585. }
  586. else
  587. nLen = 0;
  588. // get the binary
  589. try{
  590. pData = new char[nLen];
  591. ASSERT(pData);
  592. HexStringToBinary(newVal, pData, nLen);
  593. }
  594. catch(...)
  595. {
  596. hr = E_OUTOFMEMORY;
  597. goto Error;
  598. }
  599. break;
  600. default:
  601. ASSERT(0); // this should not happen
  602. break;
  603. }
  604. // check if the attriabute is RADIUS_ATTRIBUTE_TUNNEL_PASSWORD,
  605. // this attribute has special format --- remove 0's from the binary and
  606. // try to conver to text
  607. {
  608. ATTRIBUTEID Id;
  609. hr = m_spIASAttributeInfo->get_AttributeID( &Id );
  610. if( FAILED(hr) ) goto Error;
  611. if ( Id == RADIUS_ATTRIBUTE_TUNNEL_PASSWORD)
  612. {
  613. char* pData1 = NULL;
  614. // get the binary
  615. //BYTE PREFIX___RADIUS_ATTRIBUTE_TUNNEL_PASSWORD[] = {0,0,0,0};
  616. //UINT PREFIX_LEN___RADIUS_ATTRIBUTE_TUNNEL_PASSWORD = 4;
  617. //UINT PREFIX_OFFSET_DATALENBYTE___RADIUS_ATTRIBUTE_TUNNEL_PASSWORD = 3; // 0 based index -- the fourth byte
  618. //UINT PREFIX_LEN_DATALENBYTE___RADIUS_ATTRIBUTE_TUNNEL_PASSWORD = 1
  619. try{
  620. pData1 = new char[nLen + PREFIX_LEN___RADIUS_ATTRIBUTE_TUNNEL_PASSWORD];
  621. ASSERT(pData1);
  622. memcpy(pData1, PREFIX___RADIUS_ATTRIBUTE_TUNNEL_PASSWORD, PREFIX_LEN___RADIUS_ATTRIBUTE_TUNNEL_PASSWORD);
  623. unsigned char lenByte = (unsigned char)nLen;
  624. memcpy(pData1 + PREFIX_OFFSET_DATALENBYTE___RADIUS_ATTRIBUTE_TUNNEL_PASSWORD, &lenByte, PREFIX_LEN_DATALENBYTE___RADIUS_ATTRIBUTE_TUNNEL_PASSWORD);
  625. }
  626. catch(...)
  627. {
  628. hr = E_OUTOFMEMORY;
  629. goto Error;
  630. }
  631. if(pData)
  632. {
  633. memcpy(pData1 + PREFIX_LEN___RADIUS_ATTRIBUTE_TUNNEL_PASSWORD, pData, nLen);
  634. delete [] pData;
  635. pData = pData1;
  636. nLen += PREFIX_LEN___RADIUS_ATTRIBUTE_TUNNEL_PASSWORD;
  637. }
  638. }
  639. }
  640. // put the data into the safe array
  641. VariantClear(m_pvarValue);
  642. if(pData) // need to put data to safe array
  643. {
  644. SAFEARRAY* psa = NULL;
  645. SAFEARRAYBOUND sab[1];
  646. sab[0].cElements = nLen;
  647. sab[0].lLbound = 0;
  648. try{
  649. psa = SafeArrayCreate(VT_UI1, 1, sab);
  650. char* pByte = NULL;
  651. if(S_OK == SafeArrayAccessData(psa, (void**)&pByte))
  652. {
  653. ASSERT(pByte);
  654. memcpy(pByte, pData, nLen);
  655. SafeArrayUnaccessData(psa);
  656. V_VT(m_pvarValue) = VT_ARRAY | VT_UI1;
  657. V_ARRAY(m_pvarValue) = psa;
  658. }
  659. else
  660. SafeArrayDestroy(psa);
  661. }
  662. catch(...)
  663. {
  664. hr = E_OUTOFMEMORY;
  665. goto Error;
  666. }
  667. psa = NULL;
  668. };
  669. Error:
  670. if(pData)
  671. {
  672. delete [] pData;
  673. pData = NULL;
  674. }
  675. return hr;
  676. }