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.

884 lines
22 KiB

  1. /**********************************************************************/
  2. /** Microsoft Windows/NT **/
  3. /** Copyright(c) Microsoft Corporation, 1998 - 1999 **/
  4. /**********************************************************************/
  5. /*
  6. IASHelper.cpp
  7. Implementation of the following helper classes:
  8. And global functions:
  9. GetSdoInterfaceProperty - Get an interface property from a SDO
  10. through its ISdo interface
  11. FILE HISTORY:
  12. 2/18/98 byao Created
  13. */
  14. #include "Precompiled.h"
  15. #include <limits.h>
  16. #include <winsock2.h>
  17. #include "IASHelper.h"
  18. //+---------------------------------------------------------------------------
  19. //
  20. // Function: IASGetSdoInterfaceProperty
  21. //
  22. // Synopsis: Get an interface property from a SDO through its ISdo interface
  23. //
  24. // Arguments: ISdo *pISdo - Pointer to ISdo
  25. // LONG lPropId - property id
  26. // REFIID riid - ref iid
  27. // void ** ppvObject - pointer to the requested interface property
  28. //
  29. // Returns: HRESULT -
  30. //
  31. // History: Created Header byao 2/12/98 11:12:55 PM
  32. //
  33. //+---------------------------------------------------------------------------
  34. HRESULT IASGetSdoInterfaceProperty(ISdo *pISdo,
  35. LONG lPropID,
  36. REFIID riid,
  37. void ** ppvInterface)
  38. {
  39. TRACE(_T("::IASGetSdoInterfaceProperty()\n"));
  40. CComVariant var;
  41. HRESULT hr;
  42. V_VT(&var) = VT_DISPATCH;
  43. V_DISPATCH(&var) = NULL;
  44. hr = pISdo->GetProperty(lPropID, &var);
  45. //ReportError(hr, IDS_IAS_ERR_SDOERROR_GETPROPERTY, NULL);
  46. _ASSERTE( V_VT(&var) == VT_DISPATCH );
  47. // query the dispatch pointer for interface
  48. hr = V_DISPATCH(&var) -> QueryInterface( riid, ppvInterface);
  49. //ReportError(hr, IDS_IAS_ERR_SDOERROR_QUERYINTERFACE, NULL);
  50. return S_OK;
  51. }
  52. //+---------------------------------------------------------------------------
  53. //
  54. // Function: Hex2DWord
  55. //
  56. // Synopsis: hexadecimal string to dword value
  57. //
  58. // Arguments: TCHAR* tszStr - number in hexadecimal string format "FF"
  59. //
  60. // Returns: DWORD - value
  61. //
  62. // History: Created Header byao 3/6/98 2:46:49 AM
  63. //
  64. //+---------------------------------------------------------------------------
  65. DWORD Hex2DWord(TCHAR* tszStr)
  66. {
  67. TRACE(_T("::Hex2DWord()\n"));
  68. DWORD dwTemp = 0;
  69. DWORD dwDigit = 0;
  70. DWORD dwIndex = 0;
  71. for (dwIndex=0; dwIndex<_tcslen(tszStr); dwIndex++)
  72. {
  73. // get the current digit
  74. if ( tszStr[dwIndex]>= _T('0') && tszStr[dwIndex]<= _T('9') )
  75. dwDigit = tszStr[dwIndex] - _T('0');
  76. else if ( tszStr[dwIndex]>= _T('A') && tszStr[dwIndex]<= _T('F') )
  77. dwDigit = tszStr[dwIndex] - _T('A') + 10;
  78. else if ( tszStr[dwIndex]>= _T('a') && tszStr[dwIndex]<= _T('f') )
  79. dwDigit = tszStr[dwIndex] - _T('a') + 10;
  80. // accumulate the value
  81. dwTemp = dwTemp*16 + dwDigit;
  82. }
  83. return dwTemp;
  84. }
  85. //todo: where should we put these constants?
  86. #define L_INT_SIZE_BYTES 4 // from BaseCamp
  87. // position 0--1: value format
  88. #define I_VENDOR_ID_POS 2 // vendor ID starts from position 2;
  89. #define I_ATTRIBUTE_TYPE_POS 10 // either the vendor attribute type(RFC),
  90. // or raw value (for NONRFC value)
  91. //+---------------------------------------------------------------------------
  92. //
  93. // Function: GetVendorSpecificInfo
  94. //
  95. // Synopsis: Get the information for vendor-specific attribute type
  96. //
  97. // Arguments: [in]::CString& strValue - OctetString value
  98. // [out]int& dVendorId - Vendor ID
  99. // [out]fNonRFC - random/Radius RFC compatible
  100. // [out]dFormat - value format: string, integer, etc.
  101. // [out]int&dType - data type
  102. // [out]::CString&strDispValue - data displayable value
  103. //
  104. // Returns: HRESULT -
  105. //
  106. // History: Created Header byao 2/28/98 12:12:11 AM
  107. //
  108. //+---------------------------------------------------------------------------
  109. HRESULT GetVendorSpecificInfo(::CString& strValue,
  110. DWORD& dVendorId,
  111. BOOL& fNonRFC,
  112. DWORD& dFormat,
  113. DWORD& dType,
  114. ::CString& strDispValue)
  115. {
  116. TRACE(_T("::GetVendorSpecificInfo()\n"));
  117. ::CString strVSAType;
  118. ::CString strVSALen;
  119. ::CString strVSAValue;
  120. ::CString strVendorId;
  121. ::CString strPrefix;
  122. TCHAR tszTempStr[256];
  123. DWORD dwIndex;
  124. if ( strValue.GetLength() < I_ATTRIBUTE_TYPE_POS)
  125. {
  126. // invalid attribute value;
  127. strDispValue = strValue;
  128. fNonRFC = TRUE;
  129. return E_FAIL;
  130. }
  131. strDispValue.Empty();
  132. // is it a RADIUS RFC compatible value?
  133. _tcsncpy(tszTempStr, strValue, 2);
  134. tszTempStr[2] = _T('\0');
  135. switch( _ttoi(tszTempStr) )
  136. {
  137. case 0: fNonRFC = TRUE; dFormat = 0; dType = 0;
  138. break;
  139. case 1: fNonRFC = FALSE; dFormat = 0; // string
  140. break;
  141. case 2: fNonRFC = FALSE; dFormat = 1; // integer
  142. break;
  143. case 4: // ipaddress
  144. fNonRFC = FALSE; dFormat = 3; // hexadecimal
  145. break;
  146. case 3:
  147. default: fNonRFC = FALSE; dFormat = 2; // hexadecimal
  148. break;
  149. }
  150. // Vendor ID
  151. for (dwIndex=0; dwIndex<8; dwIndex++)
  152. {
  153. tszTempStr[dwIndex] = ((LPCTSTR)strValue)[I_VENDOR_ID_POS+dwIndex];
  154. }
  155. tszTempStr[dwIndex] = _T('\0');
  156. dVendorId = Hex2DWord(tszTempStr);
  157. // non RFC data?
  158. if ( fNonRFC )
  159. {
  160. _tcscpy(tszTempStr, (LPCTSTR)strValue + I_ATTRIBUTE_TYPE_POS);
  161. strDispValue = tszTempStr;
  162. }
  163. else
  164. {
  165. // Radius RFC format
  166. // find the attribute type
  167. tszTempStr[0] = ((LPCTSTR)strValue)[I_ATTRIBUTE_TYPE_POS];
  168. tszTempStr[1] = ((LPCTSTR)strValue)[I_ATTRIBUTE_TYPE_POS+1];
  169. tszTempStr[2] = _T('\0');
  170. dType = Hex2DWord(tszTempStr);
  171. TCHAR* tszPrefixStart;
  172. // find the attribute value
  173. switch(dFormat)
  174. {
  175. case 0: // string
  176. {
  177. DWORD jIndex;
  178. TCHAR tszTempChar[3];
  179. TCHAR tszTemp[2];
  180. _tcscpy(tszTempStr, (LPCTSTR)strValue+I_ATTRIBUTE_TYPE_POS+4);
  181. strDispValue = tszTempStr;
  182. /*
  183. jIndex = 0;
  184. while ( jIndex < _tcslen(tszTempStr)-1 )
  185. {
  186. tszTempChar[0] = tszTempStr[jIndex];
  187. tszTempChar[1] = tszTempStr[jIndex+1];
  188. tszTempChar[2] = _T('\0');
  189. tszTemp[0] = (TCHAR) Hex2DWord(tszTempChar);
  190. tszTemp[1] = _T('\0');
  191. strDispValue += tszTemp;
  192. jIndex += 2;
  193. }
  194. */
  195. }
  196. break;
  197. case 1: // decimal or hexadecimal
  198. tszPrefixStart = _tcsstr(strValue, _T("0x"));
  199. if (tszPrefixStart == NULL)
  200. {
  201. tszPrefixStart = _tcsstr(strValue, _T("0X"));
  202. }
  203. if (tszPrefixStart)
  204. {
  205. // hexadecimal
  206. _tcscpy(tszTempStr, tszPrefixStart);
  207. strDispValue = tszTempStr;
  208. }
  209. else
  210. {
  211. // decimal
  212. _tcscpy(tszTempStr, (LPCTSTR)strValue+I_ATTRIBUTE_TYPE_POS+4);
  213. DWORD dwValue = Hex2DWord(tszTempStr);
  214. wsprintf(tszTempStr, _T("%u"), dwValue);
  215. strDispValue = tszTempStr;
  216. }
  217. break;
  218. case 3: // ip address
  219. {
  220. // like decimal
  221. _tcscpy(tszTempStr, (LPCTSTR)strValue+I_ATTRIBUTE_TYPE_POS+4);
  222. if(_tcslen(tszTempStr) != 0)
  223. {
  224. DWORD dwValue = Hex2DWord(tszTempStr);
  225. in_addr ipaddr;
  226. ipaddr.s_addr = ntohl(dwValue);
  227. strDispValue = inet_ntoa(ipaddr);
  228. }
  229. else
  230. strDispValue = _T("");
  231. }
  232. break;
  233. case 2: // hexadecimal
  234. _tcscpy(tszTempStr, (LPCTSTR)strValue+I_ATTRIBUTE_TYPE_POS+4);
  235. strDispValue = tszTempStr;
  236. break;
  237. }
  238. }
  239. return S_OK;
  240. }
  241. //+---------------------------------------------------------------------------
  242. //
  243. // Function: SetVendorSpecificInfo
  244. //
  245. // Synopsis: Set the information for vendor-specific attribute type
  246. //
  247. // Arguments: [out]::CString& strValue - OctetString value
  248. // [in]int& dVendorId - Vendor ID
  249. // [in]fNonRFC - random or RADIUS RFC compatible
  250. // [in]dFormat - attribute format: string, integer; hexadecimal
  251. // [in]int& dType - attribute type
  252. // [in]::CString& strDispValue - data displayable value
  253. //
  254. // Returns: HRESULT -
  255. //
  256. // History: Created Header byao 2/28/98 12:12:11 AM
  257. //
  258. //+---------------------------------------------------------------------------
  259. HRESULT SetVendorSpecificInfo(::CString& strValue,
  260. DWORD& dVendorId,
  261. BOOL& fNonRFC,
  262. DWORD& dFormat,
  263. DWORD& dType,
  264. ::CString& strDispValue)
  265. {
  266. TRACE(_T("::SetVendorSpecificInfo()\n"));
  267. USES_CONVERSION;
  268. ::CString strVSAType;
  269. ::CString strVSALen;
  270. ::CString strVSAValue;
  271. ::CString strVendorId;
  272. ::CString strPrefix;
  273. TCHAR tszTempStr[256];
  274. DWORD dwIndex;
  275. wsprintf(tszTempStr, _T("%08X"), dVendorId);
  276. _tcsupr(tszTempStr);
  277. strValue = tszTempStr; // vendor ID first
  278. if ( !fNonRFC )
  279. {
  280. // RFC compatible format
  281. // prefix determined by type
  282. // 1. VendorType -- an integer between 1-255
  283. wsprintf(tszTempStr, _T("%02X"), dType);
  284. strVSAType = tszTempStr;
  285. // 2. Vendor Format: string, raw or hexadecimal
  286. switch (dFormat)
  287. {
  288. case 0: // string
  289. wsprintf(tszTempStr, _T("%02X"), _tcslen(strDispValue)+2);
  290. strVSALen = tszTempStr;
  291. /* removed per discussion with MKarki on 5/21/98.
  292. String will be saved in original format
  293. for (dwIndex=0; dwIndex<_tcslen(strDispValue); dwIndex++)
  294. {
  295. wsprintf(tszTempStr, _T("%02X"), ((LPCTSTR)strDispValue)[dwIndex]);
  296. strVSAValue += tszTempStr;
  297. }
  298. */
  299. strVSAValue = strDispValue;
  300. strPrefix = _T("01");
  301. break;
  302. case 3: // IP address : added F; 211265
  303. // the display string is in a.b.c.d format, we need to save it as decimal format
  304. //
  305. {
  306. // ip adress control
  307. unsigned long IpAddr = inet_addr(T2A(strDispValue));
  308. IpAddr = htonl(IpAddr);
  309. strPrefix = _T("04");
  310. wsprintf(tszTempStr, _T("%08lX"), IpAddr);
  311. strVSAValue = tszTempStr;
  312. // length
  313. wsprintf(tszTempStr, _T("%02X"), L_INT_SIZE_BYTES + 2);
  314. strVSALen = tszTempStr;
  315. }
  316. break;
  317. case 1: // raw -- decimal or hexadecimal (0x... format)
  318. if (_tcsstr(strDispValue, _T("0x")) != NULL ||
  319. _tcsstr(strDispValue, _T("0X")) != NULL)
  320. {
  321. // hexadecimal
  322. strVSAValue = strDispValue;
  323. }
  324. else
  325. {
  326. //todo: hexLarge???
  327. wsprintf(tszTempStr, _T("%08lX"), _ttol(strDispValue));
  328. strVSAValue = tszTempStr;
  329. }
  330. // length
  331. wsprintf(tszTempStr, _T("%02X"), L_INT_SIZE_BYTES + 2);
  332. strVSALen = tszTempStr;
  333. strPrefix = _T("02");
  334. break;
  335. case 2: // hexadecimal format
  336. wsprintf(tszTempStr, _T("%02X"), _tcslen(strDispValue)/2+2);
  337. strVSALen = tszTempStr;
  338. strVSAValue = strDispValue;
  339. strPrefix = _T("03");
  340. break;
  341. break;
  342. }
  343. if(strDispValue.IsEmpty()) // special case for nothing for value
  344. {
  345. strVSALen = _T("02");
  346. strVSAValue = _T("");
  347. }
  348. strVSAValue = strVSAType + strVSALen + strVSAValue;
  349. }
  350. else
  351. {
  352. strPrefix = _T("00");
  353. strVSAValue = strDispValue;
  354. }
  355. strValue += strVSAValue;
  356. strValue = strPrefix + strValue;
  357. return S_OK;
  358. }
  359. //+---------------------------------------------------------------------------
  360. //
  361. // Data validation and conversion routines: hexadecimal string to integer
  362. // decimal string to integer
  363. //
  364. //+---------------------------------------------------------------------------
  365. #define ISSPACE(ch) ( ( ch==_T(' ') ) || ( ch==_T('\t') ) )
  366. //+---------------------------------------------------------------------------
  367. //
  368. // Function: 'Decimal
  369. //
  370. // Synopsis: Check whether a string is a valid 4-BYTE decimal integer
  371. //
  372. // Arguments: LPCTSTR tszStr - input string
  373. // BOOL fUnsigned - whether this is an unsigned integer
  374. // long *pdValue - return the integer value back here
  375. //
  376. // Returns: BOOL - TRUE: valid decimal integer
  377. // FALSE: otherwise
  378. //
  379. // History: Created Header byao 5/22/98 2:14:14 PM
  380. //
  381. //+---------------------------------------------------------------------------
  382. BOOL IsValidDecimal(LPCTSTR tszStr, BOOL fUnsigned, long *pdValue)
  383. {
  384. if ( !tszStr )
  385. {
  386. return FALSE;
  387. }
  388. *pdValue = 0;
  389. // first, skip the white space
  390. while ( *tszStr && ISSPACE(*tszStr) )
  391. {
  392. tszStr++;
  393. }
  394. if ( ! (*tszStr) )
  395. {
  396. // string has ended already -- which means this string has only
  397. // white space in it
  398. return FALSE;
  399. }
  400. if (_tcslen(tszStr)>11)
  401. {
  402. //
  403. // since we only deal with 4-byte integer here, the standard value range
  404. // is : -2147483648 to 2147483647;
  405. // For unsigned number, that puts us to 0 to 4294967295, which has
  406. // maximum length 10.
  407. //
  408. return FALSE;
  409. }
  410. //
  411. // negative integer?
  412. //
  413. BOOL fNegative = FALSE;
  414. if ( *tszStr == _T('-') )
  415. {
  416. if ( fUnsigned )
  417. {
  418. return FALSE;
  419. }
  420. fNegative = TRUE;
  421. tszStr++;
  422. }
  423. double dbTemp = 0; // we use a temporary double variable here
  424. // so we can check whether the number is out of bounds
  425. while ( *tszStr )
  426. {
  427. if ( *tszStr <= '9' && *tszStr >='0' )
  428. {
  429. dbTemp = dbTemp*10 + (*tszStr - '0');
  430. }
  431. else
  432. {
  433. return FALSE;
  434. }
  435. tszStr++;
  436. }
  437. if ( fUnsigned && dbTemp > UINT_MAX )
  438. {
  439. // out of range
  440. return FALSE;
  441. }
  442. if ( !fUnsigned && fNegative )
  443. {
  444. // negative number??
  445. dbTemp = (-dbTemp);
  446. }
  447. if ( !fUnsigned && ( dbTemp < INT_MIN || dbTemp > INT_MAX ) )
  448. {
  449. // integer out of range
  450. return FALSE;
  451. }
  452. *pdValue = (long)dbTemp;
  453. return TRUE;
  454. }
  455. //+---------------------------------------------------------------------------
  456. //
  457. // Function: DDV_IntegerStr
  458. //
  459. // Synopsis: custom data verification routine: an integer string.
  460. // the string must be consisted of integer only and must be
  461. // in the right range for 4-byte integer
  462. //
  463. // Arguments: CDataExchange* pDX - data exchange context
  464. // ::CString& strText - string to verify
  465. //
  466. // Returns: void -
  467. //
  468. // History: Created Header byao 3/10/98 11:04:58 PM
  469. //
  470. //+---------------------------------------------------------------------------
  471. void DDV_IntegerStr(CDataExchange* pDX, ::CString& strText)
  472. {
  473. TRACE(_T("DDV_IntegerStr"));
  474. TCHAR wzMessage[MAX_PATH];
  475. ::CString strMessage;
  476. int nIndex;
  477. long lTempValue;
  478. BOOL fValid = IsValidDecimal((LPCTSTR)strText, FALSE, &lTempValue);
  479. if ( !fValid )
  480. {
  481. // invalid data
  482. ShowErrorDialog(pDX->m_pDlgWnd->GetSafeHwnd(), IDS_IAS_ERR_INVALIDINTEGER, NULL);
  483. pDX->Fail();
  484. return;
  485. }
  486. TRACE(_T("Valid integer: %ws\n"), (LPCTSTR)strText);
  487. }
  488. //+---------------------------------------------------------------------------
  489. //
  490. // Function: DDV_Unsigned_IntegerStr
  491. //
  492. // Synopsis: custom data verification routine: an unsigned integer string.
  493. // the string must be consisted of integer only and must be in
  494. // the range for a 4-byte unsigned integer
  495. //
  496. // Arguments: CDataExchange* pDX - data exchange context
  497. // ::CString& strText - string to verify
  498. //
  499. // Returns: void -
  500. //
  501. // History: Created Header byao 5/22/98 11:04:58 PM
  502. //
  503. //+---------------------------------------------------------------------------
  504. void DDV_Unsigned_IntegerStr(CDataExchange* pDX, ::CString& strText)
  505. {
  506. TRACE(_T("DDV_Unsigned_IntegerStr\n"));
  507. TCHAR wzMessage[MAX_PATH];
  508. ::CString strMessage;
  509. int nIndex;
  510. long lTempValue;
  511. BOOL fValid = IsValidDecimal((LPCTSTR)strText, TRUE, &lTempValue);
  512. if ( !fValid )
  513. {
  514. // invalid data
  515. ShowErrorDialog(pDX->m_pDlgWnd->GetSafeHwnd(), IDS_IAS_ERR_INVALID_UINT, NULL);
  516. pDX->Fail();
  517. return;
  518. }
  519. TRACE(_T("Valid integer: %ws\n"), (LPCTSTR)strText);
  520. }
  521. //+---------------------------------------------------------------------------
  522. //
  523. // Function: GetValidVSAHexString
  524. //
  525. // Synopsis: check whether the input string is a valid VSA hexadecimal string
  526. // and return a pointer to where the string actually starts
  527. //
  528. // A valid VSA hexadecimal string must meet the following criteria:
  529. // MAM 09/15/98 - _may_ start with 0x -- see 203334 -- we don't require 0x anymore.
  530. // 1) _may_ start with 0x (no preceding white space)
  531. // 2) contains only valid hexadecimal digits
  532. // 3) contains even number of digits
  533. // 4) maximum string length is 246.
  534. //
  535. // Arguments: LPCTSTR tszStr - input string
  536. //
  537. // Returns: NULL: invalid VSA hex string
  538. // otherwise return a pointer to the first character of the string
  539. //
  540. // e.g, if the string is: " 0xabcd", then return "abcd"
  541. //
  542. // History: Created Header byao 5/22/98 4:06:57 PM
  543. //
  544. //+---------------------------------------------------------------------------
  545. LPTSTR GetValidVSAHexString(LPCTSTR tszStr)
  546. {
  547. LPTSTR tszStartHex = NULL;
  548. if ( !tszStr )
  549. {
  550. return NULL;
  551. }
  552. // Maximum length: 246.
  553. // We'll check using this below once we've dispensed with
  554. // any "0x" prefix if it exists.
  555. int iMaxLength = 246;
  556. // skip the white space
  557. while ( *tszStr && ISSPACE(*tszStr) )
  558. {
  559. tszStr++;
  560. }
  561. // MAM 09/15/98 - _may_ start with 0x -- see 203334 -- we don't require 0x anymore.
  562. //
  563. // does it start with 0x?
  564. //
  565. if ( tszStr[0]==_T('0') )
  566. {
  567. // If it starts with '0x', skip these two characters.
  568. if ( tszStr[1] == _T('x') || tszStr[1] == _T('X') )
  569. {
  570. // Skip "0x" prefix.
  571. tszStr++;
  572. tszStr++;
  573. }
  574. }
  575. // Check whether exceeds iMaxLength now that we have dispensed
  576. // with "0x" if it was prefixed to the string.
  577. // Also check for minimum length: 2 (must have at least some data)
  578. // Also it must be even number length.
  579. int iLength = _tcslen(tszStr);
  580. if ( iLength > iMaxLength || iLength < 2 || iLength % 2 )
  581. {
  582. return NULL;
  583. }
  584. tszStartHex = (LPTSTR)tszStr;
  585. if ( !(*tszStartHex) )
  586. {
  587. // there's nothing followed by the prefix
  588. return NULL;
  589. }
  590. // does it contain any invalid character?
  591. while ( *tszStr )
  592. {
  593. if (!
  594. ((*tszStr >= _T('0') && *tszStr <= _T('9')) ||
  595. (*tszStr >= _T('a') && *tszStr <= _T('f')) ||
  596. (*tszStr >= _T('A') && *tszStr <= _T('F'))
  597. )
  598. )
  599. {
  600. return NULL;
  601. }
  602. tszStr++;
  603. }
  604. // return the pointer
  605. return tszStartHex;
  606. }
  607. //+---------------------------------------------------------------------------
  608. //
  609. // Function: DDV_VSA_HexString
  610. //
  611. // Synopsis: custom data verification routine: VSA hexadecimal string
  612. // A valid VSA hexadecimal string must meet the following criteria:
  613. // MAM 09/15/98 - NO! see 203334 -- we don't require 0x anymore.
  614. // 1) start with 0x (no preceding white space)
  615. // 2) contains only valid hexadecimal digits
  616. // 3) contains even number of digits
  617. // 4) maximum string length is 246.
  618. //
  619. // Arguments: CDataExchange* pDX - data exchange context
  620. // ::CString& strText - string to verify
  621. //
  622. // Returns: void -
  623. //
  624. // History: Created Header byao 5/22/98 11:04:58 PM
  625. //
  626. //+---------------------------------------------------------------------------
  627. void DDV_VSA_HexString(CDataExchange* pDX, ::CString& strText)
  628. {
  629. TRACE(_T("::DDV_VSA_HexString()\n"));
  630. TCHAR wzMessage[MAX_PATH];
  631. ::CString strMessage;
  632. LPTSTR tszHex = GetValidVSAHexString( (LPCTSTR)strText );
  633. if ( !tszHex )
  634. {
  635. // invalid data
  636. ShowErrorDialog(pDX->m_pDlgWnd->GetSafeHwnd(), IDS_IAS_ERR_INVALID_VSAHEX, NULL);
  637. pDX -> Fail();
  638. }
  639. else
  640. {
  641. strText = tszHex;
  642. TRACE(_T("Valid VSA hex string %ws\n"), (LPCTSTR)strText);
  643. }
  644. }
  645. //+---------------------------------------------------------------------------
  646. //
  647. // Function: DDV_BoolStr
  648. //
  649. // Synopsis: custom data verification routine: a boolean string.
  650. // the only valid values are "T", "F", "TRUE", "FALSE"
  651. //
  652. // Arguments: CDataExchange* pDX - data exchange context
  653. // ::CString& strText - string to verify
  654. //
  655. // Returns: void -
  656. //
  657. // History: Created Header byao 3/10/98 11:04:58 PM
  658. //
  659. //+---------------------------------------------------------------------------
  660. void DDV_BoolStr(CDataExchange* pDX, ::CString& strText)
  661. {
  662. TRACE(_T("::DDV_BoolStr()\n"));
  663. TCHAR wzMessage[MAX_PATH];
  664. ::CString strMessage;
  665. if (! ( _wcsicmp(strText, _T("TRUE")) == 0 || _wcsicmp(strText, _T("FALSE") ) == 0
  666. ))
  667. {
  668. // invalid data
  669. ShowErrorDialog(pDX->m_pDlgWnd->GetSafeHwnd(), IDS_IAS_ERR_INVALIDBOOL, NULL);
  670. pDX -> Fail();
  671. }
  672. TRACE(_T("Valid bool value %ws\n"), (LPCTSTR)strText);
  673. }
  674. //////////////////////////////////////////////////////////////////////////////
  675. TCHAR HexChar[] = {
  676. _T('0'), _T('1'), _T('2'), _T('3'), _T('4'), _T('5'), _T('6'), _T('7'),
  677. _T('8'), _T('9'), _T('a'), _T('b'), _T('c'), _T('d'), _T('e'), _T('f')
  678. };
  679. // convert binary data to hex string, bytes 01 01 01 --> _T("0x010101")
  680. size_t BinaryToHexString(char* pData, size_t cch, TCHAR* pTStr, size_t ctLen)
  681. {
  682. int nRequiredLen = (cch * 2 + 2 + 1); // two WCHAR for 1 byte, and 0x at begining and , \0 at end
  683. if(ctLen == 0)
  684. return nRequiredLen;
  685. if(ctLen < nRequiredLen || pTStr == NULL || pData == NULL)
  686. return 0;
  687. // make the output string empty
  688. if(cch == 0)
  689. {
  690. *pTStr = 0;
  691. return 1;
  692. }
  693. // do converstion now
  694. *pTStr = _T('0');
  695. *(pTStr + 1) = _T('x');
  696. // walk through each byte
  697. for(int i = 0; i < cch; i++)
  698. {
  699. int h = ((*(pData + i) & 0xf0) >> 4);
  700. // high 4 bits
  701. *(pTStr + i * 2 + 2) = HexChar[h];
  702. // low 4 bits
  703. h = (*(pData + i) & 0x0f);
  704. *(pTStr + i * 2 + 1+ 2 ) = HexChar[h];
  705. }
  706. *(pTStr + nRequiredLen - 1 ) = _T('\0');
  707. return nRequiredLen;
  708. }
  709. //
  710. #define HexValue(h) \
  711. ( ((h) >= _T('a') && (h) <= _T('f')) ? ((h) - _T('a') + 0xa) : \
  712. ( ((h) >= _T('A') && (h) <= _T('F')) ? ((h) - _T('A') + 0xa) : \
  713. ( ((h) >= _T('0') && (h) <= _T('9')) ? ((h) - _T('0')) : 0)))
  714. // convert HexString to binary value: _T("0x010101") convert to 3 bytes 01 01 01
  715. size_t HexStringToBinary(TCHAR* pStr, char* pData, size_t cch)
  716. {
  717. // need to convert to binary before passing into SafeArray
  718. pStr = GetValidVSAHexString(pStr);
  719. if(pStr == NULL) return 0;
  720. size_t nLen = _tcslen(pStr) / 2;
  721. // if inquery for length
  722. if(cch == 0) return nLen;
  723. // get the binary
  724. for(int i = 0; i < nLen; i++)
  725. {
  726. char h, l;
  727. // high 4 bits
  728. h = (char)HexValue(pStr[i * 2]);
  729. // low 4 bits
  730. l = (char)HexValue(pStr[i * 2 + 1]);
  731. *(pData + i) = (h << 4) + l;
  732. }
  733. return nLen;
  734. }