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.

2631 lines
86 KiB

  1. //+---------------------------------------------------------------------------
  2. //
  3. // Microsoft Windows
  4. // Copyright (C) Microsoft Corporation, 1992-2000.
  5. //
  6. // File: variable.cxx
  7. //
  8. // Contents: Used to replace variables
  9. //
  10. // History: 96/Jan/3 DwightKr Created
  11. //
  12. //----------------------------------------------------------------------------
  13. #include <pch.cxx>
  14. #pragma hdrstop
  15. void RenderSafeArray(
  16. VARTYPE vt,
  17. SAFEARRAY * psa,
  18. COutputFormat & outputFormat,
  19. CVirtualString & vString,
  20. BOOL fFormatted );
  21. //+---------------------------------------------------------------------------
  22. //
  23. // Member: CVariable::CVariable - public constructor
  24. //
  25. // Synopsis: Builds a single replaceable variable based in a propVariant
  26. //
  27. // Arguments: [wcsName] - friendly name for the variable
  28. // [pVariant] - the variable's value
  29. // [ulFlags] - all flags associated with this variable, for
  30. // now this indicates if this variable requires
  31. // a IRowsetScroll to access its value.
  32. //
  33. // History: 96/Jan/03 DwightKr Created.
  34. //
  35. //----------------------------------------------------------------------------
  36. CVariable::CVariable( WCHAR const * wcsName,
  37. PROPVARIANT const * pVariant,
  38. ULONG ulFlags ) :
  39. _wcsName(0),
  40. _wcsRAWValue(0),
  41. _cwcRAWValue(0),
  42. _eNumType( eNotANumber ),
  43. _ulFlags(ulFlags),
  44. _pNext(0),
  45. _pBack(0)
  46. {
  47. Win4Assert( wcsName != 0 );
  48. ULONG cwcName = wcslen(wcsName) + 1;
  49. _wcsName = new WCHAR[ cwcName ];
  50. RtlCopyMemory( _wcsName, wcsName, cwcName * sizeof(WCHAR) );
  51. _variant.vt = VT_EMPTY;
  52. _variant.pwszVal = 0;
  53. if ( 0 != pVariant )
  54. {
  55. // SetValue cannot raise
  56. SetValue( pVariant, ulFlags );
  57. }
  58. }
  59. //+---------------------------------------------------------------------------
  60. //
  61. // Member: CVariable::CVariable - public copy constructor
  62. //
  63. // Synopsis: Builds a single replaceable variable based in a propVariant
  64. //
  65. // Arguments: [variable] - the variable to copy
  66. //
  67. // History: 96/Jan/03 DwightKr Created.
  68. //
  69. //----------------------------------------------------------------------------
  70. CVariable::CVariable( const CVariable & variable ) :
  71. _wcsName(0),
  72. _cwcRAWValue(0),
  73. _eNumType( variable._eNumType ),
  74. _ulFlags(0),
  75. _pNext(0)
  76. {
  77. ULONG cwcName = wcslen(variable._wcsName) + 1;
  78. _wcsName = new WCHAR[ cwcName ];
  79. RtlCopyMemory( _wcsName, variable._wcsName, cwcName * sizeof(WCHAR) );
  80. _ulFlags = variable._ulFlags;
  81. _variant = variable._variant;
  82. if ( VT_LPWSTR == variable._variant.vt )
  83. {
  84. _cwcRAWValue = variable._cwcRAWValue;
  85. }
  86. }
  87. //+---------------------------------------------------------------------------
  88. //
  89. // Member: CVariable::~CVariable - public destructor
  90. //
  91. // History: 96/Jan/03 DwightKr Created.
  92. //
  93. //----------------------------------------------------------------------------
  94. CVariable::~CVariable()
  95. {
  96. if ( (_ulFlags & eParamOwnsVariantMemory) != 0 )
  97. {
  98. delete _variant.pwszVal;
  99. }
  100. //
  101. // If we have a RAW string that is not part of the variant, and is
  102. // not pointing to the in-line number buffer, delete it. It's probably
  103. // an ASCII string we've converted to WCHAR.
  104. //
  105. if ( _wcsRAWValue &&
  106. _wcsRAWValue != _wcsNumberValue &&
  107. _wcsRAWValue != _variant.pwszVal )
  108. {
  109. delete _wcsRAWValue;
  110. }
  111. delete _wcsName;
  112. if ( 0 != _pNext )
  113. delete _pNext;
  114. }
  115. //+---------------------------------------------------------------------------
  116. //
  117. // Member: CVariable::SetValue - public
  118. //
  119. // Synopsis: An assignment operator; allows the value of a variable to
  120. // be changed.
  121. //
  122. // Arguments: [pVariant] - new value for this variable
  123. //
  124. // History: 96/Jan/03 DwightKr Created.
  125. //
  126. //----------------------------------------------------------------------------
  127. void CVariable::SetValue( PROPVARIANT const * pVariant, ULONG ulFlags )
  128. {
  129. //
  130. // If we've stored a string equivalent for the old value, then
  131. // delete it now.
  132. //
  133. if ( _wcsRAWValue &&
  134. _wcsRAWValue != _wcsNumberValue &&
  135. _wcsRAWValue != _variant.pwszVal )
  136. {
  137. delete _wcsRAWValue;
  138. _wcsRAWValue = 0;
  139. _cwcRAWValue = 0;
  140. _eNumType = eNotANumber;
  141. }
  142. if ( (_ulFlags & eParamOwnsVariantMemory) != 0 )
  143. {
  144. delete _variant.pwszVal;
  145. _variant.pwszVal = 0;
  146. _ulFlags &= ~eParamOwnsVariantMemory;
  147. }
  148. if ( 0 != pVariant )
  149. _variant = *pVariant;
  150. else
  151. {
  152. _variant.vt = VT_EMPTY;
  153. _variant.pwszVal = 0; // retentive
  154. }
  155. //
  156. // If its a WCHAR string, we already have a pointer to its RAW value.
  157. //
  158. if ( (VT_LPWSTR == _variant.vt) && (0 != _variant.pwszVal) )
  159. {
  160. _wcsRAWValue = _variant.pwszVal;
  161. _cwcRAWValue = wcslen(_wcsRAWValue);
  162. }
  163. else
  164. {
  165. _wcsRAWValue = 0;
  166. _cwcRAWValue = 0;
  167. }
  168. _ulFlags |= ulFlags;
  169. }
  170. //+---------------------------------------------------------------------------
  171. //
  172. // Member: CVariable::FastSetValue - public
  173. //
  174. // Synopsis: Special version of SetValue that can be faster because it
  175. // knows that the variable can't own variant memory, that
  176. // the variant is non-0, that the flags are 0, and that variant
  177. // wide strings are non-zero.
  178. //
  179. // Arguments: [pVariant] - new value for this variable
  180. //
  181. // History: 96/Apr/05 dlee Created.
  182. //
  183. //----------------------------------------------------------------------------
  184. void CVariable::FastSetValue( PROPVARIANT const * pVariant )
  185. {
  186. //
  187. // If we've stored a string equivalent for the old value, then
  188. // delete it now.
  189. //
  190. if ( ( _wcsRAWValue != _wcsNumberValue ) &&
  191. ( _wcsRAWValue != _variant.pwszVal ) )
  192. {
  193. delete _wcsRAWValue;
  194. _wcsRAWValue = 0;
  195. _cwcRAWValue = 0;
  196. }
  197. _eNumType = eNotANumber;
  198. Win4Assert( (_ulFlags & eParamOwnsVariantMemory) == 0 );
  199. Win4Assert( 0 != pVariant );
  200. _variant = *pVariant;
  201. if ( VT_LPWSTR == _variant.vt )
  202. {
  203. // The caller of FastSetValue can't pass a 0 string variant
  204. Win4Assert( 0 != _variant.pwszVal );
  205. _wcsRAWValue = _variant.pwszVal;
  206. _cwcRAWValue = wcslen(_wcsRAWValue);
  207. }
  208. else
  209. {
  210. _wcsRAWValue = 0;
  211. _cwcRAWValue = 0;
  212. }
  213. }
  214. //+---------------------------------------------------------------------------
  215. //
  216. // Member: CVariable::SetValue - public
  217. //
  218. // Synopsis: A assignment operator; allows the value of a variable to
  219. // be changed. Ownership of the string is transferred to this
  220. // function
  221. //
  222. // Arguments: [wcsValue] - new value for this variable
  223. // [cwcValue] - length of new value string
  224. //
  225. // History: 96/Jan/03 DwightKr Created.
  226. //
  227. //----------------------------------------------------------------------------
  228. void CVariable::SetValue( XPtrST<WCHAR> & wcsValue, ULONG cwcValue )
  229. {
  230. Win4Assert( VT_LPWSTR == _variant.vt );
  231. //
  232. // If we've stored a string equivalent for the old value, then
  233. // delete it now.
  234. //
  235. if ( _wcsRAWValue &&
  236. _wcsRAWValue != _wcsNumberValue &&
  237. _wcsRAWValue != _variant.pwszVal )
  238. {
  239. delete _wcsRAWValue;
  240. _wcsRAWValue = 0;
  241. _cwcRAWValue = 0;
  242. _eNumType = eNotANumber;
  243. }
  244. if ( (_ulFlags & eParamOwnsVariantMemory) != 0 )
  245. {
  246. delete _variant.pwszVal;
  247. _variant.pwszVal = 0;
  248. }
  249. _ulFlags |= eParamOwnsVariantMemory;
  250. _wcsRAWValue = wcsValue.Acquire();
  251. _cwcRAWValue = cwcValue;
  252. }
  253. // Maximum length of a floating point value string
  254. // Big enough for a 1e308 + 9 decimal places + sign
  255. const unsigned maxFloatSize = 320;
  256. // Floating point precision.
  257. // +1 because the numbers in float.h seem to be too small by one digit.
  258. const unsigned fltPrec = FLT_DIG+1;
  259. const unsigned dblPrec = DBL_DIG+1;
  260. //+---------------------------------------------------------------------------
  261. //
  262. // Function: SARenderElementFormatted
  263. //
  264. // Synopsis: Appends the formatted string form a safearray element to
  265. // a virtual string.
  266. // Only the subset of types that are formatted differently
  267. // when "formatted" vs "raw" are handled in this function.
  268. //
  269. // Arguments: [outputFormat] -- The output format to use
  270. // [vString] -- Where the result is appended
  271. // [vt] -- Type of the element
  272. // [pv] -- Pointer to the element
  273. //
  274. // Notes: I8 and UI8 aren't allowed in safearrays in NT 5, but they
  275. // will be someday.
  276. //
  277. // History: 9-Jun-98 dlee Created
  278. //
  279. //----------------------------------------------------------------------------
  280. void SARenderElementFormatted(
  281. COutputFormat & outputFormat,
  282. CVirtualString & vString,
  283. VARTYPE vt,
  284. void * pv )
  285. {
  286. ciGibDebugOut(( DEB_ITRACE, "vt %#x, pv %#x\n", vt, pv ));
  287. // Recurse if we have a nested VT_ARRAY in an array element.
  288. if ( VT_ARRAY & vt )
  289. {
  290. SAFEARRAY *psa = *(SAFEARRAY **) pv;
  291. RenderSafeArray( vt & ~VT_ARRAY, psa, outputFormat, vString, TRUE );
  292. return;
  293. }
  294. WCHAR awcTmp[ maxFloatSize ];
  295. const ULONG cwcTmp = sizeof awcTmp / sizeof awcTmp[0];
  296. ULONG cwc = 0;
  297. switch ( vt )
  298. {
  299. case VT_UI1:
  300. {
  301. cwc = outputFormat.FormatNumber( (ULONG) * (BYTE *) pv,
  302. awcTmp,
  303. cwcTmp );
  304. break;
  305. }
  306. case VT_I1:
  307. {
  308. cwc = outputFormat.FormatNumber( (LONG) * (signed char *) pv,
  309. awcTmp,
  310. cwcTmp );
  311. break;
  312. }
  313. case VT_UI2:
  314. {
  315. USHORT us;
  316. RtlCopyMemory( &us, pv, sizeof us );
  317. cwc = outputFormat.FormatNumber( (ULONG) us,
  318. awcTmp,
  319. cwcTmp );
  320. break;
  321. }
  322. case VT_I2:
  323. {
  324. SHORT s;
  325. RtlCopyMemory( &s, pv, sizeof s );
  326. cwc = outputFormat.FormatNumber( (LONG) s,
  327. awcTmp,
  328. cwcTmp );
  329. break;
  330. }
  331. case VT_UI4:
  332. case VT_UINT:
  333. {
  334. ULONG ul;
  335. RtlCopyMemory( &ul, pv, sizeof ul );
  336. cwc = outputFormat.FormatNumber( ul,
  337. awcTmp,
  338. cwcTmp );
  339. break;
  340. }
  341. case VT_I4:
  342. case VT_ERROR:
  343. case VT_INT:
  344. {
  345. LONG l;
  346. RtlCopyMemory( &l, pv, sizeof l );
  347. cwc = outputFormat.FormatNumber( l,
  348. awcTmp,
  349. cwcTmp );
  350. break;
  351. }
  352. case VT_UI8:
  353. {
  354. unsigned __int64 ui;
  355. RtlCopyMemory( &ui, pv, sizeof ui );
  356. cwc = outputFormat.FormatNumber( ui,
  357. awcTmp,
  358. cwcTmp );
  359. break;
  360. }
  361. case VT_I8:
  362. {
  363. __int64 i;
  364. RtlCopyMemory( &i, pv, sizeof i );
  365. cwc = outputFormat.FormatNumber( i,
  366. awcTmp,
  367. cwcTmp );
  368. break;
  369. }
  370. case VT_R4:
  371. {
  372. float f;
  373. RtlCopyMemory( &f, pv, sizeof f );
  374. cwc = outputFormat.FormatFloat( f,
  375. fltPrec,
  376. awcTmp,
  377. cwcTmp );
  378. break;
  379. }
  380. case VT_R8:
  381. {
  382. double d;
  383. RtlCopyMemory( &d, pv, sizeof d );
  384. cwc = outputFormat.FormatFloat( d,
  385. dblPrec,
  386. awcTmp,
  387. cwcTmp );
  388. break;
  389. }
  390. case VT_DECIMAL:
  391. {
  392. double d;
  393. VarR8FromDec( (DECIMAL *) pv, &d );
  394. cwc = outputFormat.FormatFloat( d,
  395. dblPrec,
  396. awcTmp,
  397. cwcTmp );
  398. break;
  399. }
  400. case VT_CY:
  401. {
  402. double d;
  403. VarR8FromCy( * (CY *) pv, &d );
  404. cwc = outputFormat.FormatFloat( d,
  405. dblPrec,
  406. awcTmp,
  407. cwcTmp );
  408. break;
  409. }
  410. case VT_VARIANT:
  411. {
  412. PROPVARIANT & Var = * (PROPVARIANT *) pv;
  413. SARenderElementFormatted( outputFormat, vString, Var.vt, & Var.lVal );
  414. break;
  415. }
  416. default :
  417. {
  418. ciGibDebugOut(( DEB_ERROR, "unexpected numeric sa element type %#x\n", vt ));
  419. Win4Assert( !"unexpected numeric safearray element type" );
  420. break;
  421. }
  422. }
  423. vString.StrCat( awcTmp, cwc );
  424. } //SARenderElementFormatted
  425. //+---------------------------------------------------------------------------
  426. //
  427. // Function: SARenderElementRaw
  428. //
  429. // Synopsis: Appends the "raw" string form a safearray element to
  430. // a virtual string. Numbers are raw when they don't have
  431. // formatting like commas.
  432. //
  433. // Arguments: [outputFormat] -- The output format to use
  434. // [vString] -- Where the result is appended
  435. // [vt] -- Type of the element
  436. // [pv] -- Pointer to the element
  437. //
  438. // Notes: I8 and UI8 aren't allowed in safearrays in NT 5, but they
  439. // will be someday.
  440. //
  441. // History: 9-Jun-98 dlee Created
  442. //
  443. //----------------------------------------------------------------------------
  444. void SARenderElementRaw(
  445. COutputFormat & outputFormat,
  446. CVirtualString & vString,
  447. VARTYPE vt,
  448. void * pv )
  449. {
  450. ciGibDebugOut(( DEB_ITRACE, "vt %#x, pv %#x\n", vt, pv ));
  451. // Recurse if we have a nested VT_ARRAY in an array element.
  452. if ( VT_ARRAY & vt )
  453. {
  454. SAFEARRAY *psa = *(SAFEARRAY **) pv;
  455. RenderSafeArray( vt & ~VT_ARRAY, psa, outputFormat, vString, FALSE );
  456. return;
  457. }
  458. WCHAR awcTmp[ maxFloatSize ];
  459. const ULONG cwcTmp = sizeof awcTmp / sizeof awcTmp[0];
  460. ULONG cwc = 0;
  461. switch ( vt )
  462. {
  463. case VT_EMPTY:
  464. case VT_NULL:
  465. {
  466. break;
  467. }
  468. case VT_BSTR:
  469. {
  470. BSTR bstr = *(BSTR *) pv;
  471. vString.StrCat( bstr );
  472. break;
  473. }
  474. case VT_BOOL:
  475. {
  476. VARIANT_BOOL vb;
  477. RtlCopyMemory( &vb, pv, sizeof vb );
  478. wcscpy( awcTmp, ( VARIANT_FALSE == vb ) ? L"FALSE" : L"TRUE" );
  479. cwc = wcslen( awcTmp);
  480. break;
  481. }
  482. case VT_DATE:
  483. {
  484. SYSTEMTIME stUTC;
  485. DATE date;
  486. RtlCopyMemory( &date, pv, sizeof date );
  487. if ( VariantTimeToSystemTime( date, &stUTC ) )
  488. cwc = outputFormat.FormatDateTime( stUTC,
  489. awcTmp,
  490. cwcTmp );
  491. break;
  492. }
  493. case VT_UI1:
  494. {
  495. IDQ_ultow( (ULONG) * (BYTE *) pv, awcTmp );
  496. cwc = wcslen( awcTmp );
  497. break;
  498. }
  499. case VT_I1:
  500. {
  501. IDQ_ltow( (LONG) * (signed char *) pv, awcTmp );
  502. cwc = wcslen( awcTmp );
  503. break;
  504. }
  505. case VT_UI2:
  506. {
  507. USHORT us;
  508. RtlCopyMemory( &us, pv, sizeof us );
  509. IDQ_ultow( (ULONG) us, awcTmp );
  510. cwc = wcslen( awcTmp );
  511. break;
  512. }
  513. case VT_I2:
  514. {
  515. SHORT s;
  516. RtlCopyMemory( &s, pv, sizeof s );
  517. IDQ_ltow( (LONG) s, awcTmp );
  518. cwc = wcslen( awcTmp );
  519. break;
  520. }
  521. case VT_UI4:
  522. case VT_UINT:
  523. {
  524. ULONG ul;
  525. RtlCopyMemory( &ul, pv, sizeof ul );
  526. IDQ_ultow( ul, awcTmp );
  527. cwc = wcslen( awcTmp );
  528. break;
  529. }
  530. case VT_I4:
  531. case VT_ERROR:
  532. case VT_INT:
  533. {
  534. LONG l;
  535. RtlCopyMemory( &l, pv, sizeof l );
  536. IDQ_ltow( l, awcTmp );
  537. cwc = wcslen( awcTmp );
  538. break;
  539. }
  540. case VT_UI8:
  541. {
  542. unsigned __int64 ui;
  543. RtlCopyMemory( &ui, pv, sizeof ui );
  544. IDQ_ulltow( ui, awcTmp );
  545. cwc = wcslen( awcTmp );
  546. break;
  547. }
  548. case VT_I8:
  549. {
  550. __int64 i;
  551. RtlCopyMemory( &i, pv, sizeof i );
  552. IDQ_lltow( i, awcTmp );
  553. cwc = wcslen( awcTmp );
  554. break;
  555. }
  556. case VT_R4:
  557. {
  558. float f;
  559. RtlCopyMemory( &f, pv, sizeof f );
  560. cwc = outputFormat.FormatFloatRaw( f,
  561. fltPrec,
  562. awcTmp,
  563. cwcTmp );
  564. break;
  565. }
  566. case VT_R8:
  567. {
  568. double d;
  569. RtlCopyMemory( &d, pv, sizeof d );
  570. cwc = outputFormat.FormatFloatRaw( d,
  571. dblPrec,
  572. awcTmp,
  573. cwcTmp );
  574. break;
  575. }
  576. case VT_DECIMAL:
  577. {
  578. double d;
  579. VarR8FromDec( (DECIMAL *) pv, &d );
  580. cwc = outputFormat.FormatFloatRaw( d,
  581. dblPrec,
  582. awcTmp,
  583. cwcTmp );
  584. break;
  585. }
  586. case VT_CY:
  587. {
  588. double d;
  589. VarR8FromCy( * (CY *) pv, &d );
  590. cwc = outputFormat.FormatFloatRaw( d,
  591. dblPrec,
  592. awcTmp,
  593. cwcTmp );
  594. break;
  595. }
  596. case VT_VARIANT:
  597. {
  598. PROPVARIANT & Var = * (PROPVARIANT *) pv;
  599. SARenderElementRaw( outputFormat, vString, Var.vt, & Var.lVal );
  600. break;
  601. }
  602. default :
  603. {
  604. ciGibDebugOut(( DEB_ERROR, "unexpected sa element type %#x\n", vt ));
  605. Win4Assert( !"unexpected safearray element type" );
  606. break;
  607. }
  608. }
  609. vString.StrCat( awcTmp, cwc );
  610. } //SARenderElementRaw
  611. //+---------------------------------------------------------------------------
  612. //
  613. // Function: GetVectorFormatting
  614. //
  615. // Synopsis: Retrieves the vector formatting strings for a given type.
  616. // Only safearray element datatypes are handled here.
  617. //
  618. // Arguments: [pwcPre] -- Returns the vector prefix string
  619. // [pwcSep] -- Returns the vector separator string
  620. // [pwcSuf] -- Returns the vector suffix string
  621. //
  622. // History: 9-Jun-98 dlee Created
  623. //
  624. //----------------------------------------------------------------------------
  625. void GetVectorFormatting(
  626. WCHAR const * & pwcPre,
  627. WCHAR const * & pwcSep,
  628. WCHAR const * & pwcSuf,
  629. VARTYPE vt,
  630. COutputFormat & outputFormat )
  631. {
  632. Win4Assert( 0 == ( vt & VT_ARRAY ) );
  633. switch ( vt )
  634. {
  635. case VT_CY:
  636. pwcPre = outputFormat.GetCurrencyVectorPrefix();
  637. pwcSep = outputFormat.GetCurrencyVectorSeparator();
  638. pwcSuf = outputFormat.GetCurrencyVectorSuffix();
  639. break;
  640. case VT_DATE:
  641. pwcPre = outputFormat.GetDateVectorPrefix();
  642. pwcSep = outputFormat.GetDateVectorSeparator();
  643. pwcSuf = outputFormat.GetDateVectorSuffix();
  644. break;
  645. case VT_BOOL:
  646. pwcPre = outputFormat.GetBoolVectorPrefix();
  647. pwcSep = outputFormat.GetBoolVectorSeparator();
  648. pwcSuf = outputFormat.GetBoolVectorSuffix();
  649. break;
  650. case VT_BSTR:
  651. pwcPre = outputFormat.GetStringVectorPrefix();
  652. pwcSep = outputFormat.GetStringVectorSeparator();
  653. pwcSuf = outputFormat.GetStringVectorSuffix();
  654. break;
  655. case VT_VARIANT:
  656. case VT_EMPTY:
  657. case VT_NULL:
  658. case VT_I1:
  659. case VT_UI1:
  660. case VT_I2:
  661. case VT_UI2:
  662. case VT_I4:
  663. case VT_INT:
  664. case VT_UI4:
  665. case VT_UINT:
  666. case VT_I8:
  667. case VT_UI8:
  668. case VT_R4:
  669. case VT_R8:
  670. case VT_DECIMAL:
  671. case VT_ERROR:
  672. pwcPre = outputFormat.GetNumberVectorPrefix();
  673. pwcSep = outputFormat.GetNumberVectorSeparator();
  674. pwcSuf = outputFormat.GetNumberVectorSuffix();
  675. break;
  676. default:
  677. ciGibDebugOut(( DEB_ERROR, "GetVectorFormatting unknown type %#x\n", vt ));
  678. Win4Assert( !"GetVectorFormatting doesn't support type" );
  679. break;
  680. }
  681. } //GetVectorFormatting
  682. //+---------------------------------------------------------------------------
  683. //
  684. // Function: RenderSafeArray
  685. //
  686. // Synopsis: Appends the string form of a safearray to a virtual string.
  687. //
  688. // Arguments: [vt] -- Datatype of the safearray, without VT_ARRAY
  689. // [psa] -- The safearray to format
  690. // [outputFormat] -- How to render the result
  691. // [vString] -- The result is appended here
  692. // [fFormatted] -- If TRUE, formatted, otherwise raw
  693. //
  694. // History: 9-Jun-98 dlee Created
  695. //
  696. //----------------------------------------------------------------------------
  697. void RenderSafeArray(
  698. VARTYPE vt,
  699. SAFEARRAY * psa,
  700. COutputFormat & outputFormat,
  701. CVirtualString & vString,
  702. BOOL fFormatted )
  703. {
  704. Win4Assert( 0 == ( vt & VT_ARRAY ) );
  705. //
  706. // Get the array prefix, separator, and suffix
  707. //
  708. WCHAR const * pwcPre;
  709. WCHAR const * pwcSep;
  710. WCHAR const * pwcSuf;
  711. GetVectorFormatting( pwcPre, pwcSep, pwcSuf, vt, outputFormat );
  712. //
  713. // Get the dimensions of the array
  714. //
  715. CDynArrayInPlace<WCHAR> xOut;
  716. UINT cDim = SafeArrayGetDim( psa );
  717. if ( 0 == cDim )
  718. return;
  719. XArray<LONG> xDim( cDim );
  720. XArray<LONG> xLo( cDim );
  721. XArray<LONG> xUp( cDim );
  722. for ( UINT iDim = 0; iDim < cDim; iDim++ )
  723. {
  724. SCODE sc = SafeArrayGetLBound( psa, iDim + 1, &xLo[iDim] );
  725. if ( FAILED( sc ) )
  726. THROW( CException( sc ) );
  727. xDim[ iDim ] = xLo[ iDim ];
  728. sc = SafeArrayGetUBound( psa, iDim + 1, &xUp[iDim] );
  729. if ( FAILED( sc ) )
  730. THROW( CException( sc ) );
  731. ciGibDebugOut(( DEB_ITRACE, "dim %d, lo %d, up %d\n",
  732. iDim, xLo[iDim], xUp[iDim] ));
  733. vString.StrCat( pwcPre );
  734. }
  735. //
  736. // Slog through the array
  737. //
  738. UINT iLastDim = cDim - 1;
  739. BOOL fDone = FALSE;
  740. while ( !fDone )
  741. {
  742. // Inter-element formatting if not the first element
  743. if ( xDim[ iLastDim ] != xLo[ iLastDim ] )
  744. vString.StrCat( pwcSep );
  745. // Get the element and render it
  746. void *pv;
  747. SCODE sc = SafeArrayPtrOfIndex( psa, xDim.GetPointer(), &pv );
  748. if ( FAILED( sc ) )
  749. THROW( CException( sc ) );
  750. if ( fFormatted )
  751. SARenderElementFormatted( outputFormat, vString, vt, pv );
  752. else
  753. SARenderElementRaw( outputFormat, vString, vt, pv );
  754. // Move to the next element and carry if necessary
  755. ULONG cOpen = 0;
  756. for ( LONG iDim = iLastDim; iDim >= 0; iDim-- )
  757. {
  758. if ( xDim[ iDim ] < xUp[ iDim ] )
  759. {
  760. xDim[ iDim ] = 1 + xDim[ iDim ];
  761. break;
  762. }
  763. vString.StrCat( pwcSuf );
  764. if ( 0 == iDim )
  765. fDone = TRUE;
  766. else
  767. {
  768. cOpen++;
  769. xDim[ iDim ] = xLo[ iDim ];
  770. }
  771. }
  772. for ( ULONG i = 0; !fDone && i < cOpen; i++ )
  773. vString.StrCat( pwcPre );
  774. }
  775. } //RenderSafeArray
  776. //+---------------------------------------------------------------------------
  777. //
  778. // Member: CVariable::GetStringValueFormattedRAW - public
  779. //
  780. // Synopsis: Not all VT types are strings. Those which are not strings
  781. // have a string equivalent generated and stored for reuse.
  782. //
  783. // Arguments: [outputFormat] - contains formatting information for numbers
  784. //
  785. // Returns: A pointer to a string representation of the variable's value.
  786. // Numbers are formatted.
  787. //
  788. // History: 26-Aug-96 KyleP Created (from GetStringValueRAW)
  789. //
  790. //----------------------------------------------------------------------------
  791. WCHAR * CVariable::GetStringValueFormattedRAW( COutputFormat & outputFormat,
  792. ULONG & cwcValue )
  793. {
  794. Win4Assert( !(_wcsRAWValue == 0 && _cwcRAWValue != 0) );
  795. //
  796. // Did we have a real raw value last time?
  797. //
  798. if ( _wcsRAWValue && _eNumType == eRawNumber )
  799. {
  800. if ( _wcsRAWValue != _wcsNumberValue && _wcsRAWValue != _variant.pwszVal )
  801. delete _wcsRAWValue;
  802. _wcsRAWValue = 0;
  803. _cwcRAWValue = 0;
  804. }
  805. if ( 0 == _wcsRAWValue )
  806. {
  807. switch ( _variant.vt )
  808. {
  809. case VT_UI1:
  810. _cwcRAWValue = outputFormat.FormatNumber( (ULONG) _variant.bVal,
  811. _wcsNumberValue,
  812. sizeof(_wcsNumberValue) / sizeof(WCHAR) );
  813. _wcsRAWValue = _wcsNumberValue;
  814. _eNumType = eFormattedNumber;
  815. break;
  816. case VT_I1:
  817. _cwcRAWValue = outputFormat.FormatNumber( (LONG) _variant.cVal,
  818. _wcsNumberValue,
  819. sizeof(_wcsNumberValue) / sizeof(WCHAR) );
  820. _wcsRAWValue = _wcsNumberValue;
  821. _eNumType = eFormattedNumber;
  822. break;
  823. case VT_UI2:
  824. _cwcRAWValue = outputFormat.FormatNumber( (ULONG) _variant.uiVal,
  825. _wcsNumberValue,
  826. sizeof(_wcsNumberValue) / sizeof(WCHAR) );
  827. _wcsRAWValue = _wcsNumberValue;
  828. _eNumType = eFormattedNumber;
  829. break;
  830. case VT_I2:
  831. _cwcRAWValue = outputFormat.FormatNumber( (LONG) _variant.iVal,
  832. _wcsNumberValue,
  833. sizeof(_wcsNumberValue) / sizeof(WCHAR) );
  834. _wcsRAWValue = _wcsNumberValue;
  835. _eNumType = eFormattedNumber;
  836. break;
  837. case VT_UI4:
  838. case VT_UINT:
  839. _cwcRAWValue = outputFormat.FormatNumber( (ULONG) _variant.ulVal,
  840. _wcsNumberValue,
  841. sizeof(_wcsNumberValue) / sizeof(WCHAR) );
  842. _wcsRAWValue = _wcsNumberValue;
  843. _eNumType = eFormattedNumber;
  844. break;
  845. case VT_I4:
  846. case VT_INT:
  847. case VT_ERROR:
  848. _cwcRAWValue = outputFormat.FormatNumber( (LONG) _variant.lVal,
  849. _wcsNumberValue,
  850. sizeof(_wcsNumberValue) / sizeof(WCHAR) );
  851. _wcsRAWValue = _wcsNumberValue;
  852. _eNumType = eFormattedNumber;
  853. break;
  854. case VT_UI8:
  855. _cwcRAWValue = outputFormat.FormatNumber( _variant.uhVal.QuadPart,
  856. _wcsNumberValue,
  857. sizeof(_wcsNumberValue) / sizeof(WCHAR) );
  858. _wcsRAWValue = _wcsNumberValue;
  859. _eNumType = eFormattedNumber;
  860. break;
  861. case VT_I8:
  862. _cwcRAWValue = outputFormat.FormatNumber( _variant.hVal.QuadPart,
  863. _wcsNumberValue,
  864. sizeof(_wcsNumberValue) / sizeof(WCHAR) );
  865. _wcsRAWValue = _wcsNumberValue;
  866. _eNumType = eFormattedNumber;
  867. break;
  868. case VT_R4:
  869. {
  870. WCHAR awchOutput[maxFloatSize];
  871. _cwcRAWValue = outputFormat.FormatFloat( _variant.fltVal,
  872. fltPrec,
  873. awchOutput,
  874. maxFloatSize );
  875. if ( _cwcRAWValue < cwcNumberValue )
  876. _wcsRAWValue = _wcsNumberValue;
  877. else
  878. _wcsRAWValue = new WCHAR[ 1 + _cwcRAWValue ];
  879. RtlCopyMemory( _wcsRAWValue, awchOutput, (1 + _cwcRAWValue) * sizeof WCHAR );
  880. _eNumType = eFormattedNumber;
  881. break;
  882. }
  883. case VT_R8:
  884. case VT_DECIMAL:
  885. {
  886. double dblValue = _variant.dblVal;
  887. if ( VT_DECIMAL == _variant.vt )
  888. VarR8FromDec( &_variant.decVal, &dblValue );
  889. // Big enough for a 1e308 + 9 decimal places + sign
  890. WCHAR awchOutput[maxFloatSize];
  891. _cwcRAWValue = outputFormat.FormatFloat( dblValue,
  892. dblPrec,
  893. awchOutput,
  894. maxFloatSize );
  895. if ( _cwcRAWValue < cwcNumberValue )
  896. _wcsRAWValue = _wcsNumberValue;
  897. else
  898. _wcsRAWValue = new WCHAR[ 1 + _cwcRAWValue ];
  899. RtlCopyMemory( _wcsRAWValue, awchOutput, (1 + _cwcRAWValue) * sizeof WCHAR );
  900. _eNumType = eFormattedNumber;
  901. break;
  902. }
  903. case VT_CY:
  904. _cwcRAWValue = outputFormat.FormatCurrency( _variant.cyVal,
  905. _wcsNumberValue,
  906. sizeof(_wcsNumberValue) / sizeof(WCHAR) );
  907. _wcsRAWValue = _wcsNumberValue;
  908. _eNumType = eFormattedNumber;
  909. break;
  910. case VT_UI1 | VT_VECTOR:
  911. case VT_I1 | VT_VECTOR:
  912. {
  913. _eNumType = eFormattedNumber;
  914. CVirtualString vString( 0x200 );
  915. vString.StrCat( outputFormat.GetNumberVectorPrefix() );
  916. for ( unsigned iValue=0;
  917. iValue<_variant.caub.cElems;
  918. iValue++ )
  919. {
  920. if ( 0 != iValue )
  921. vString.StrCat( outputFormat.GetNumberVectorSeparator() );
  922. if ( (VT_UI1 | VT_VECTOR) == _variant.vt )
  923. _cwcRAWValue = outputFormat.FormatNumber( (ULONG) _variant.caub.pElems[iValue],
  924. _wcsNumberValue,
  925. sizeof(_wcsNumberValue) / sizeof(WCHAR) );
  926. else
  927. _cwcRAWValue = outputFormat.FormatNumber( (LONG) _variant.cac.pElems[iValue],
  928. _wcsNumberValue,
  929. sizeof(_wcsNumberValue) / sizeof(WCHAR) );
  930. vString.StrCat( _wcsNumberValue, _cwcRAWValue );
  931. }
  932. vString.StrCat( outputFormat.GetNumberVectorSuffix() );
  933. _wcsRAWValue = vString.StrDup();
  934. _cwcRAWValue = vString.StrLen();
  935. break;
  936. }
  937. case VT_I2 | VT_VECTOR:
  938. case VT_UI2 | VT_VECTOR:
  939. {
  940. _eNumType = eFormattedNumber;
  941. CVirtualString vString( 0x200 );
  942. vString.StrCat( outputFormat.GetNumberVectorPrefix() );
  943. for ( unsigned iValue=0;
  944. iValue<_variant.caui.cElems;
  945. iValue++ )
  946. {
  947. if ( 0 != iValue )
  948. vString.StrCat( outputFormat.GetNumberVectorSeparator() );
  949. if ( (VT_UI2 | VT_VECTOR) == _variant.vt )
  950. _cwcRAWValue = outputFormat.FormatNumber( (ULONG) _variant.caui.pElems[iValue],
  951. _wcsNumberValue,
  952. sizeof(_wcsNumberValue) / sizeof(WCHAR) );
  953. else
  954. _cwcRAWValue = outputFormat.FormatNumber( (LONG) _variant.cai.pElems[iValue],
  955. _wcsNumberValue,
  956. sizeof(_wcsNumberValue) / sizeof(WCHAR) );
  957. vString.StrCat( _wcsNumberValue, _cwcRAWValue );
  958. }
  959. vString.StrCat( outputFormat.GetNumberVectorSuffix() );
  960. _wcsRAWValue = vString.StrDup();
  961. _cwcRAWValue = vString.StrLen();
  962. break;
  963. }
  964. case VT_R4 | VT_VECTOR:
  965. case VT_I4 | VT_VECTOR:
  966. case VT_UI4 | VT_VECTOR:
  967. case VT_ERROR | VT_VECTOR:
  968. {
  969. _eNumType = eFormattedNumber;
  970. CVirtualString vString( 0x200 );
  971. vString.StrCat( outputFormat.GetNumberVectorPrefix() );
  972. for ( unsigned iValue=0;
  973. iValue<_variant.caul.cElems;
  974. iValue++ )
  975. {
  976. if ( 0 != iValue )
  977. vString.StrCat( outputFormat.GetNumberVectorSeparator() );
  978. if ( (VT_R4 | VT_VECTOR) == _variant.vt )
  979. _cwcRAWValue = outputFormat.FormatFloat( _variant.caflt.pElems[iValue],
  980. fltPrec,
  981. _wcsNumberValue,
  982. sizeof(_wcsNumberValue) / sizeof(WCHAR) );
  983. else if ( (VT_UI4 | VT_VECTOR) == _variant.vt )
  984. _cwcRAWValue = outputFormat.FormatNumber( _variant.caul.pElems[iValue],
  985. _wcsNumberValue,
  986. sizeof(_wcsNumberValue) / sizeof(WCHAR) );
  987. else
  988. _cwcRAWValue = outputFormat.FormatNumber( _variant.cal.pElems[iValue],
  989. _wcsNumberValue,
  990. sizeof(_wcsNumberValue) / sizeof(WCHAR) );
  991. vString.StrCat( _wcsNumberValue, _cwcRAWValue );
  992. }
  993. vString.StrCat( outputFormat.GetNumberVectorSuffix() );
  994. _wcsRAWValue = vString.StrDup();
  995. _cwcRAWValue = vString.StrLen();
  996. break;
  997. }
  998. case VT_I8 | VT_VECTOR:
  999. case VT_UI8 | VT_VECTOR:
  1000. case VT_R8 | VT_VECTOR:
  1001. {
  1002. _eNumType = eFormattedNumber;
  1003. CVirtualString vString( 0x200 );
  1004. vString.StrCat( outputFormat.GetNumberVectorPrefix() );
  1005. for ( unsigned iValue=0;
  1006. iValue<_variant.cadbl.cElems;
  1007. iValue++
  1008. )
  1009. {
  1010. if ( 0 != iValue )
  1011. vString.StrCat( outputFormat.GetNumberVectorSeparator() );
  1012. if ( (VT_I8 | VT_VECTOR) == _variant.vt )
  1013. _cwcRAWValue = outputFormat.FormatNumber( (_int64) _variant.cah.pElems[iValue].QuadPart,
  1014. _wcsNumberValue,
  1015. sizeof(_wcsNumberValue) / sizeof(WCHAR) );
  1016. else if ( (VT_UI8 | VT_VECTOR) == _variant.vt )
  1017. _cwcRAWValue = outputFormat.FormatNumber( (unsigned _int64) _variant.cauh.pElems[iValue].QuadPart,
  1018. _wcsNumberValue,
  1019. sizeof(_wcsNumberValue) / sizeof(WCHAR) );
  1020. else
  1021. _cwcRAWValue = outputFormat.FormatFloat( _variant.cadbl.pElems[iValue],
  1022. dblPrec,
  1023. _wcsNumberValue,
  1024. sizeof(_wcsNumberValue) / sizeof(WCHAR) );
  1025. vString.StrCat( _wcsNumberValue, _cwcRAWValue );
  1026. }
  1027. vString.StrCat( outputFormat.GetNumberVectorSuffix() );
  1028. _wcsRAWValue = vString.StrDup();
  1029. _cwcRAWValue = vString.StrLen();
  1030. break;
  1031. }
  1032. case VT_CY | VT_VECTOR:
  1033. {
  1034. _eNumType = eFormattedNumber;
  1035. CVirtualString vString( 0x200 );
  1036. vString.StrCat( outputFormat.GetCurrencyVectorPrefix() );
  1037. for ( unsigned iValue=0;
  1038. iValue<_variant.cacy.cElems;
  1039. iValue++ )
  1040. {
  1041. if ( 0 != iValue )
  1042. vString.StrCat( outputFormat.GetCurrencyVectorSeparator() );
  1043. _cwcRAWValue = outputFormat.FormatCurrency( _variant.cacy.pElems[iValue],
  1044. _wcsNumberValue,
  1045. sizeof(_wcsNumberValue) / sizeof(WCHAR) );
  1046. vString.StrCat( _wcsNumberValue, _cwcRAWValue );
  1047. }
  1048. vString.StrCat( outputFormat.GetCurrencyVectorSuffix() );
  1049. _wcsRAWValue = vString.StrDup();
  1050. _cwcRAWValue = vString.StrLen();
  1051. break;
  1052. }
  1053. case VT_ARRAY | VT_I1 :
  1054. case VT_ARRAY | VT_UI1:
  1055. case VT_ARRAY | VT_I2 :
  1056. case VT_ARRAY | VT_UI2 :
  1057. case VT_ARRAY | VT_I4 :
  1058. case VT_ARRAY | VT_INT :
  1059. case VT_ARRAY | VT_UI4 :
  1060. case VT_ARRAY | VT_UINT :
  1061. case VT_ARRAY | VT_CY :
  1062. case VT_ARRAY | VT_DECIMAL :
  1063. case VT_ARRAY | VT_ERROR:
  1064. {
  1065. _eNumType = eFormattedNumber;
  1066. CVirtualString vString( 0x200 );
  1067. RenderSafeArray( _variant.vt & ~VT_ARRAY,
  1068. _variant.parray,
  1069. outputFormat,
  1070. vString,
  1071. TRUE );
  1072. _wcsRAWValue = vString.StrDup();
  1073. _cwcRAWValue = vString.StrLen();
  1074. break;
  1075. }
  1076. default:
  1077. {
  1078. Win4Assert( _eNumType == eNotANumber );
  1079. GetStringValueRAW( outputFormat, cwcValue );
  1080. break;
  1081. }
  1082. }
  1083. }
  1084. #if (DBG == 1)
  1085. if ( _wcsRAWValue != 0 )
  1086. {
  1087. Win4Assert( wcslen(_wcsRAWValue) == _cwcRAWValue );
  1088. }
  1089. #endif // DBG == 1
  1090. Win4Assert( !(_wcsRAWValue == 0 && _cwcRAWValue != 0) );
  1091. cwcValue = _cwcRAWValue;
  1092. return _wcsRAWValue;
  1093. }
  1094. //+---------------------------------------------------------------------------
  1095. //
  1096. // Member: CVariable::GetStringValueRAW - public
  1097. //
  1098. // Synopsis: Not all VT types are strings. Those which are not strings
  1099. // have a string equivalent generated and stored for reuse.
  1100. //
  1101. // Arguments: [outputFormat] - contains formatting information for numbers
  1102. //
  1103. // Returns: A pointer to a string representation of the variable's value.
  1104. //
  1105. // History: 96/Jan/03 DwightKr Created.
  1106. // 96/Mar/29 DwightKr Add support for deferred VT_LPWSTR
  1107. // values
  1108. //
  1109. //----------------------------------------------------------------------------
  1110. WCHAR * CVariable::GetStringValueRAW( COutputFormat & outputFormat,
  1111. ULONG & cwcValue)
  1112. {
  1113. Win4Assert( !(_wcsRAWValue == 0 && _cwcRAWValue != 0) );
  1114. //
  1115. // Did we have a formatted raw value last time?
  1116. //
  1117. if ( _wcsRAWValue && _eNumType == eFormattedNumber )
  1118. {
  1119. if ( _wcsRAWValue != _wcsNumberValue && _wcsRAWValue != _variant.pwszVal )
  1120. delete _wcsRAWValue;
  1121. _wcsRAWValue = 0;
  1122. _cwcRAWValue = 0;
  1123. }
  1124. if ( 0 == _wcsRAWValue )
  1125. {
  1126. switch ( _variant.vt )
  1127. {
  1128. case VT_LPWSTR:
  1129. //
  1130. // if it's a deferred value, load it now
  1131. //
  1132. if ( (_ulFlags & eParamDeferredValue) != 0 )
  1133. {
  1134. XArray<WCHAR> wcsValue;
  1135. ULONG cwcValue;
  1136. if ( outputFormat.GetCGIVariableW(_wcsName, wcsValue, cwcValue) )
  1137. {
  1138. _wcsRAWValue = wcsValue.Acquire();
  1139. _cwcRAWValue = cwcValue;
  1140. ciGibDebugOut(( DEB_ITRACE,
  1141. "Loading deferred value for %ws=%ws\n",
  1142. _wcsName,
  1143. _wcsRAWValue ));
  1144. }
  1145. else
  1146. {
  1147. ciGibDebugOut(( DEB_ITRACE,
  1148. "Unable to load deferred value for %ws\n",
  1149. _wcsName ));
  1150. _variant.vt = VT_EMPTY;
  1151. _wcsRAWValue = _wcsNumberValue;
  1152. *_wcsRAWValue = 0;
  1153. _cwcRAWValue = 0;
  1154. }
  1155. break;
  1156. }
  1157. // fall through if not a deferred value
  1158. case VT_EMPTY:
  1159. _wcsRAWValue = _wcsNumberValue;
  1160. *_wcsRAWValue = 0;
  1161. _cwcRAWValue = 0;
  1162. break;
  1163. case VT_BSTR:
  1164. _wcsRAWValue = _variant.bstrVal;
  1165. _cwcRAWValue = wcslen( _wcsRAWValue );
  1166. break;
  1167. case VT_LPSTR:
  1168. {
  1169. ULONG cbBuffer = strlen( _variant.pszVal ) + 1;
  1170. XArray<WCHAR> pwBuffer;
  1171. _cwcRAWValue = MultiByteToXArrayWideChar(
  1172. (BYTE * const) _variant.pszVal,
  1173. cbBuffer,
  1174. outputFormat.CodePage(),
  1175. pwBuffer );
  1176. _wcsRAWValue = pwBuffer.Acquire();
  1177. }
  1178. break;
  1179. case VT_UI1:
  1180. IDQ_ultow( (ULONG) _variant.bVal, _wcsNumberValue );
  1181. _wcsRAWValue = _wcsNumberValue;
  1182. _cwcRAWValue = wcslen( _wcsRAWValue );
  1183. _eNumType = eRawNumber;
  1184. break;
  1185. case VT_I1:
  1186. IDQ_ltow( (LONG) _variant.cVal, _wcsNumberValue );
  1187. _wcsRAWValue = _wcsNumberValue;
  1188. _cwcRAWValue = wcslen( _wcsRAWValue );
  1189. _eNumType = eRawNumber;
  1190. break;
  1191. case VT_UI2:
  1192. IDQ_ultow( (ULONG) _variant.uiVal, _wcsNumberValue );
  1193. _wcsRAWValue = _wcsNumberValue;
  1194. _cwcRAWValue = wcslen( _wcsRAWValue );
  1195. _eNumType = eRawNumber;
  1196. break;
  1197. case VT_I2:
  1198. IDQ_ltow( (LONG) _variant.iVal, _wcsNumberValue );
  1199. _wcsRAWValue = _wcsNumberValue;
  1200. _cwcRAWValue = wcslen( _wcsRAWValue );
  1201. _eNumType = eRawNumber;
  1202. break;
  1203. case VT_UI4:
  1204. case VT_UINT:
  1205. IDQ_ultow( _variant.ulVal, _wcsNumberValue );
  1206. _wcsRAWValue = _wcsNumberValue;
  1207. _cwcRAWValue = wcslen( _wcsRAWValue );
  1208. _eNumType = eRawNumber;
  1209. break;
  1210. case VT_I4:
  1211. case VT_INT:
  1212. case VT_ERROR:
  1213. IDQ_ltow( _variant.lVal, _wcsNumberValue );
  1214. _wcsRAWValue = _wcsNumberValue;
  1215. _cwcRAWValue = wcslen( _wcsRAWValue );
  1216. _eNumType = eRawNumber;
  1217. break;
  1218. case VT_UI8:
  1219. IDQ_ulltow( _variant.uhVal.QuadPart, _wcsNumberValue );
  1220. _wcsRAWValue = _wcsNumberValue;
  1221. _cwcRAWValue = wcslen( _wcsRAWValue );
  1222. _eNumType = eRawNumber;
  1223. break;
  1224. case VT_I8:
  1225. IDQ_lltow( _variant.hVal.QuadPart, _wcsNumberValue );
  1226. _wcsRAWValue = _wcsNumberValue;
  1227. _cwcRAWValue = wcslen( _wcsRAWValue );
  1228. _eNumType = eRawNumber;
  1229. break;
  1230. case VT_R4:
  1231. {
  1232. // Big enough for a 1e308 + 9 decimal places + sign
  1233. WCHAR awc[maxFloatSize];
  1234. outputFormat.FormatFloatRaw( _variant.fltVal, fltPrec, awc, maxFloatSize );
  1235. _cwcRAWValue = wcslen( awc );
  1236. if ( _cwcRAWValue < cwcNumberValue )
  1237. _wcsRAWValue = _wcsNumberValue;
  1238. else
  1239. _wcsRAWValue = new WCHAR[ 1 + _cwcRAWValue ];
  1240. RtlCopyMemory( _wcsRAWValue, awc, (1 + _cwcRAWValue) * sizeof WCHAR );
  1241. _eNumType = eRawNumber;
  1242. }
  1243. break;
  1244. case VT_R8:
  1245. case VT_DECIMAL:
  1246. {
  1247. double dblValue = _variant.dblVal;
  1248. if ( VT_DECIMAL == _variant.vt )
  1249. VarR8FromDec( &_variant.decVal, &dblValue );
  1250. // Big enough for a 1e308 + 9 decimal places + sign
  1251. WCHAR awc[maxFloatSize];
  1252. outputFormat.FormatFloatRaw( dblValue, dblPrec, awc, maxFloatSize );
  1253. _cwcRAWValue = wcslen( awc );
  1254. if ( _cwcRAWValue < cwcNumberValue )
  1255. _wcsRAWValue = _wcsNumberValue;
  1256. else
  1257. _wcsRAWValue = new WCHAR[ 1 + _cwcRAWValue ];
  1258. RtlCopyMemory( _wcsRAWValue, awc, (1 + _cwcRAWValue) * sizeof WCHAR );
  1259. _eNumType = eRawNumber;
  1260. }
  1261. break;
  1262. case VT_DATE:
  1263. {
  1264. //
  1265. // variantdate => dosdate => utcfiletime
  1266. //
  1267. SYSTEMTIME stUTC;
  1268. if ( VariantTimeToSystemTime(_variant.date, &stUTC ) )
  1269. {
  1270. _cwcRAWValue = outputFormat.FormatDateTime( stUTC,
  1271. _wcsNumberValue,
  1272. sizeof(_wcsNumberValue) / sizeof(WCHAR) );
  1273. _wcsRAWValue = _wcsNumberValue;
  1274. }
  1275. else
  1276. {
  1277. _wcsRAWValue = _wcsNumberValue;
  1278. *_wcsRAWValue = 0;
  1279. _cwcRAWValue = 0;
  1280. }
  1281. }
  1282. break;
  1283. case VT_FILETIME:
  1284. _cwcRAWValue = outputFormat.FormatDateTime( _variant.filetime,
  1285. _wcsNumberValue,
  1286. sizeof(_wcsNumberValue) / sizeof(WCHAR) );
  1287. _wcsRAWValue = _wcsNumberValue;
  1288. break;
  1289. case VT_BOOL:
  1290. _wcsRAWValue = _wcsNumberValue;
  1291. wcscpy( _wcsRAWValue, _variant.boolVal == VARIANT_FALSE ? L"FALSE" : L"TRUE" );
  1292. _cwcRAWValue = wcslen( _wcsRAWValue );
  1293. break;
  1294. case VT_CLSID:
  1295. _wcsRAWValue = _wcsNumberValue;
  1296. _cwcRAWValue = swprintf( _wcsRAWValue,
  1297. L"%08lx-%04x-%04x-%02x%02x-%02x%02x%02x%02x%02x%02x",
  1298. _variant.puuid->Data1,
  1299. _variant.puuid->Data2,
  1300. _variant.puuid->Data3,
  1301. _variant.puuid->Data4[0], _variant.puuid->Data4[1],
  1302. _variant.puuid->Data4[2], _variant.puuid->Data4[3],
  1303. _variant.puuid->Data4[4], _variant.puuid->Data4[5],
  1304. _variant.puuid->Data4[6], _variant.puuid->Data4[7] );
  1305. break;
  1306. case VT_CY:
  1307. {
  1308. double dblValue;
  1309. VarR8FromCy( _variant.cyVal, &dblValue );
  1310. // Big enough for a 1e308 + 9 decimal places + sign
  1311. WCHAR awc[maxFloatSize];
  1312. _cwcRAWValue = swprintf( awc, L"%lf", dblValue );
  1313. if ( _cwcRAWValue < cwcNumberValue )
  1314. _wcsRAWValue = _wcsNumberValue;
  1315. else
  1316. _wcsRAWValue = new WCHAR[ 1 + _cwcRAWValue ];
  1317. RtlCopyMemory( _wcsRAWValue, awc, (1 + _cwcRAWValue) * sizeof WCHAR );
  1318. _eNumType = eRawNumber;
  1319. }
  1320. break;
  1321. //
  1322. // Vectors only below this point
  1323. //
  1324. case VT_LPWSTR | VT_VECTOR:
  1325. {
  1326. CVirtualString vString( 0x200 );
  1327. vString.StrCat( outputFormat.GetStringVectorPrefix() );
  1328. for ( unsigned iValue=0;
  1329. iValue<_variant.calpwstr.cElems;
  1330. iValue++ )
  1331. {
  1332. if ( 0 != iValue )
  1333. vString.StrCat( outputFormat.GetStringVectorSeparator() );
  1334. vString.StrCat( _variant.calpwstr.pElems[iValue] );
  1335. }
  1336. vString.StrCat( outputFormat.GetStringVectorSuffix() );
  1337. _wcsRAWValue = vString.StrDup();
  1338. _cwcRAWValue = vString.StrLen();
  1339. }
  1340. break;
  1341. case VT_BSTR | VT_VECTOR:
  1342. {
  1343. CVirtualString vString( 0x200 );
  1344. vString.StrCat( outputFormat.GetStringVectorPrefix() );
  1345. for ( unsigned iValue=0;
  1346. iValue<_variant.cabstr.cElems;
  1347. iValue++ )
  1348. {
  1349. if ( 0 != iValue )
  1350. vString.StrCat( outputFormat.GetStringVectorSeparator() );
  1351. vString.StrCat( _variant.cabstr.pElems[iValue] );
  1352. }
  1353. vString.StrCat( outputFormat.GetStringVectorSuffix() );
  1354. _wcsRAWValue = vString.StrDup();
  1355. _cwcRAWValue = vString.StrLen();
  1356. }
  1357. break;
  1358. case VT_LPSTR | VT_VECTOR:
  1359. {
  1360. CVirtualString vString( 0x200 );
  1361. vString.StrCat( outputFormat.GetStringVectorPrefix() );
  1362. for ( unsigned iValue=0;
  1363. iValue<_variant.calpstr.cElems;
  1364. iValue++ )
  1365. {
  1366. if ( 0 != iValue )
  1367. vString.StrCat( outputFormat.GetStringVectorSeparator() );
  1368. ULONG cbBuffer = strlen( _variant.calpstr.pElems[iValue] ) + 1;
  1369. XArray<WCHAR> pwBuffer;
  1370. _cwcRAWValue = MultiByteToXArrayWideChar(
  1371. (BYTE * const) _variant.calpstr.pElems[iValue],
  1372. cbBuffer,
  1373. outputFormat.CodePage(),
  1374. pwBuffer );
  1375. vString.StrCat( pwBuffer.Get(), _cwcRAWValue );
  1376. }
  1377. vString.StrCat( outputFormat.GetStringVectorSuffix() );
  1378. _wcsRAWValue = vString.StrDup();
  1379. _cwcRAWValue = vString.StrLen();
  1380. }
  1381. break;
  1382. case VT_UI1 | VT_VECTOR:
  1383. case VT_I1 | VT_VECTOR:
  1384. {
  1385. _eNumType = eRawNumber;
  1386. CVirtualString vString( 0x200 );
  1387. vString.StrCat( outputFormat.GetNumberVectorPrefix() );
  1388. for ( unsigned iValue=0;
  1389. iValue<_variant.caub.cElems;
  1390. iValue++ )
  1391. {
  1392. if ( 0 != iValue )
  1393. vString.StrCat( outputFormat.GetNumberVectorSeparator() );
  1394. if ( (VT_UI1 | VT_VECTOR) == _variant.vt )
  1395. {
  1396. IDQ_ultow( (ULONG) _variant.caub.pElems[iValue], _wcsNumberValue );
  1397. _wcsRAWValue = _wcsNumberValue;
  1398. _cwcRAWValue = wcslen( _wcsRAWValue );
  1399. }
  1400. else
  1401. {
  1402. IDQ_ltow( (LONG) _variant.cac.pElems[iValue], _wcsNumberValue );
  1403. _wcsRAWValue = _wcsNumberValue;
  1404. _cwcRAWValue = wcslen( _wcsRAWValue );
  1405. }
  1406. vString.StrCat( _wcsNumberValue, _cwcRAWValue );
  1407. }
  1408. vString.StrCat( outputFormat.GetNumberVectorSuffix() );
  1409. _wcsRAWValue = vString.StrDup();
  1410. _cwcRAWValue = vString.StrLen();
  1411. }
  1412. break;
  1413. case VT_I2 | VT_VECTOR:
  1414. case VT_UI2 | VT_VECTOR:
  1415. {
  1416. _eNumType = eRawNumber;
  1417. CVirtualString vString( 0x200 );
  1418. vString.StrCat( outputFormat.GetNumberVectorPrefix() );
  1419. for ( unsigned iValue=0;
  1420. iValue<_variant.caui.cElems;
  1421. iValue++ )
  1422. {
  1423. if ( 0 != iValue )
  1424. vString.StrCat( outputFormat.GetNumberVectorSeparator() );
  1425. if ( (VT_UI2 | VT_VECTOR) == _variant.vt )
  1426. {
  1427. IDQ_ultow( (ULONG) _variant.caui.pElems[iValue], _wcsNumberValue );
  1428. _wcsRAWValue = _wcsNumberValue;
  1429. _cwcRAWValue = wcslen( _wcsRAWValue );
  1430. }
  1431. else
  1432. {
  1433. IDQ_ltow( (LONG) _variant.cai.pElems[iValue], _wcsNumberValue );
  1434. _wcsRAWValue = _wcsNumberValue;
  1435. _cwcRAWValue = wcslen( _wcsRAWValue );
  1436. }
  1437. vString.StrCat( _wcsNumberValue, _cwcRAWValue );
  1438. }
  1439. vString.StrCat( outputFormat.GetNumberVectorSuffix() );
  1440. _wcsRAWValue = vString.StrDup();
  1441. _cwcRAWValue = vString.StrLen();
  1442. }
  1443. break;
  1444. case VT_I4 | VT_VECTOR:
  1445. case VT_UI4 | VT_VECTOR:
  1446. case VT_I8 | VT_VECTOR:
  1447. case VT_UI8 | VT_VECTOR:
  1448. {
  1449. _eNumType = eRawNumber;
  1450. CVirtualString vString( 0x200 );
  1451. vString.StrCat( outputFormat.GetNumberVectorPrefix() );
  1452. for ( unsigned iValue=0;
  1453. iValue<_variant.caul.cElems;
  1454. iValue++ )
  1455. {
  1456. if ( 0 != iValue )
  1457. vString.StrCat( outputFormat.GetNumberVectorSeparator() );
  1458. if ( (VT_I4 | VT_VECTOR) == _variant.vt )
  1459. {
  1460. IDQ_ltow( _variant.cal.pElems[iValue], _wcsNumberValue );
  1461. _wcsRAWValue = _wcsNumberValue;
  1462. _cwcRAWValue = wcslen( _wcsRAWValue );
  1463. }
  1464. else if ( (VT_UI4 | VT_VECTOR) == _variant.vt )
  1465. {
  1466. IDQ_ultow( _variant.caul.pElems[iValue], _wcsNumberValue );
  1467. _wcsRAWValue = _wcsNumberValue;
  1468. _cwcRAWValue = wcslen( _wcsRAWValue );
  1469. }
  1470. else if ( (VT_I8 | VT_VECTOR) == _variant.vt )
  1471. {
  1472. IDQ_lltow( _variant.cah.pElems[iValue].QuadPart, _wcsNumberValue );
  1473. _wcsRAWValue = _wcsNumberValue;
  1474. _cwcRAWValue = wcslen( _wcsRAWValue );
  1475. }
  1476. else
  1477. {
  1478. IDQ_ulltow( _variant.cauh.pElems[iValue].QuadPart, _wcsNumberValue );
  1479. _wcsRAWValue = _wcsNumberValue;
  1480. _cwcRAWValue = wcslen( _wcsRAWValue );
  1481. }
  1482. vString.StrCat( _wcsNumberValue, _cwcRAWValue );
  1483. }
  1484. vString.StrCat( outputFormat.GetNumberVectorSuffix() );
  1485. _wcsRAWValue = vString.StrDup();
  1486. _cwcRAWValue = vString.StrLen();
  1487. }
  1488. break;
  1489. case VT_R4 | VT_VECTOR:
  1490. case VT_R8 | VT_VECTOR:
  1491. {
  1492. _eNumType = eRawNumber;
  1493. CVirtualString vString( 0x200 );
  1494. vString.StrCat( outputFormat.GetNumberVectorPrefix() );
  1495. // Big enough for a 1e308 + 9 decimal places + sign
  1496. WCHAR awc[maxFloatSize];
  1497. for ( unsigned iValue=0;
  1498. iValue<_variant.cadbl.cElems;
  1499. iValue++ )
  1500. {
  1501. if ( 0 != iValue )
  1502. vString.StrCat( outputFormat.GetNumberVectorSeparator() );
  1503. if ( (VT_R4 | VT_VECTOR) == _variant.vt )
  1504. {
  1505. outputFormat.FormatFloatRaw( _variant.caflt.pElems[iValue], fltPrec, awc, maxFloatSize );
  1506. _cwcRAWValue = wcslen( awc );
  1507. }
  1508. else
  1509. {
  1510. outputFormat.FormatFloatRaw( _variant.cadbl.pElems[iValue], dblPrec, awc, maxFloatSize );
  1511. _cwcRAWValue = wcslen( awc );
  1512. }
  1513. vString.StrCat( awc, _cwcRAWValue );
  1514. }
  1515. vString.StrCat( outputFormat.GetNumberVectorSuffix() );
  1516. _wcsRAWValue = vString.StrDup();
  1517. _cwcRAWValue = vString.StrLen();
  1518. }
  1519. break;
  1520. case VT_DATE | VT_VECTOR:
  1521. {
  1522. CVirtualString vString( 0x200 );
  1523. vString.StrCat( outputFormat.GetDateVectorPrefix() );
  1524. for ( unsigned iValue=0;
  1525. iValue<_variant.cadate.cElems;
  1526. iValue++ )
  1527. {
  1528. if ( 0 != iValue )
  1529. vString.StrCat( outputFormat.GetDateVectorSeparator() );
  1530. //
  1531. // variantdate => dosdate => localfiletime => utcfiletime
  1532. //
  1533. SYSTEMTIME stUTC;
  1534. if ( VariantTimeToSystemTime(_variant.cadate.pElems[iValue], &stUTC ) )
  1535. {
  1536. _cwcRAWValue = outputFormat.FormatDateTime( stUTC,
  1537. _wcsNumberValue,
  1538. sizeof(_wcsNumberValue) / sizeof(WCHAR) );
  1539. }
  1540. else
  1541. {
  1542. *_wcsNumberValue = 0;
  1543. _cwcRAWValue = 0;
  1544. }
  1545. vString.StrCat( _wcsNumberValue, _cwcRAWValue );
  1546. }
  1547. vString.StrCat( outputFormat.GetDateVectorSuffix() );
  1548. _wcsRAWValue = vString.StrDup();
  1549. _cwcRAWValue = vString.StrLen();
  1550. }
  1551. break;
  1552. case VT_FILETIME | VT_VECTOR:
  1553. {
  1554. CVirtualString vString( 0x200 );
  1555. vString.StrCat( outputFormat.GetDateVectorPrefix() );
  1556. for ( unsigned iValue=0;
  1557. iValue<_variant.cafiletime.cElems;
  1558. iValue++ )
  1559. {
  1560. if ( 0 != iValue )
  1561. vString.StrCat( outputFormat.GetDateVectorSeparator() );
  1562. _cwcRAWValue = outputFormat.FormatDateTime( _variant.cafiletime.pElems[iValue],
  1563. _wcsNumberValue,
  1564. sizeof(_wcsNumberValue) / sizeof(WCHAR) );
  1565. vString.StrCat( _wcsNumberValue, _cwcRAWValue );
  1566. }
  1567. vString.StrCat( outputFormat.GetDateVectorSuffix() );
  1568. _wcsRAWValue = vString.StrDup();
  1569. _cwcRAWValue = vString.StrLen();
  1570. }
  1571. break;
  1572. case VT_BOOL | VT_VECTOR:
  1573. {
  1574. CVirtualString vString( 0x200 );
  1575. vString.StrCat( outputFormat.GetBoolVectorPrefix() );
  1576. for ( unsigned iValue=0;
  1577. iValue<_variant.cabool.cElems;
  1578. iValue++ )
  1579. {
  1580. if ( 0 != iValue )
  1581. vString.StrCat( outputFormat.GetBoolVectorSeparator() );
  1582. vString.StrCat( _variant.cabool.pElems[iValue] == VARIANT_FALSE ? L"FALSE" : L"TRUE" );
  1583. }
  1584. vString.StrCat( outputFormat.GetBoolVectorSuffix() );
  1585. _wcsRAWValue = vString.StrDup();
  1586. _cwcRAWValue = vString.StrLen();
  1587. }
  1588. break;
  1589. case VT_CLSID | VT_VECTOR:
  1590. {
  1591. CVirtualString vString( 0x200 );
  1592. vString.StrCat( outputFormat.GetStringVectorPrefix() );
  1593. for ( unsigned iValue=0;
  1594. iValue<_variant.cauuid.cElems;
  1595. iValue++ )
  1596. {
  1597. if ( 0 != iValue )
  1598. vString.StrCat( outputFormat.GetStringVectorSeparator() );
  1599. _cwcRAWValue = swprintf( _wcsNumberValue,
  1600. L"%08lx-%04x-%04x-%02x%02x-%02x%02x%02x%02x%02x%02x",
  1601. _variant.cauuid.pElems[iValue].Data1,
  1602. _variant.cauuid.pElems[iValue].Data2,
  1603. _variant.cauuid.pElems[iValue].Data3,
  1604. _variant.cauuid.pElems[iValue].Data4[0], _variant.cauuid.pElems[iValue].Data4[1],
  1605. _variant.cauuid.pElems[iValue].Data4[2], _variant.cauuid.pElems[iValue].Data4[3],
  1606. _variant.cauuid.pElems[iValue].Data4[4], _variant.cauuid.pElems[iValue].Data4[5],
  1607. _variant.cauuid.pElems[iValue].Data4[6], _variant.cauuid.pElems[iValue].Data4[7] );
  1608. vString.StrCat( _wcsNumberValue, _cwcRAWValue );
  1609. }
  1610. vString.StrCat( outputFormat.GetStringVectorSuffix() );
  1611. _wcsRAWValue = vString.StrDup();
  1612. _cwcRAWValue = vString.StrLen();
  1613. }
  1614. break;
  1615. case VT_CY | VT_VECTOR:
  1616. {
  1617. _eNumType = eRawNumber;
  1618. CVirtualString vString( 0x200 );
  1619. vString.StrCat( outputFormat.GetCurrencyVectorPrefix() );
  1620. for ( unsigned iValue=0;
  1621. iValue<_variant.cacy.cElems;
  1622. iValue++ )
  1623. {
  1624. if ( 0 != iValue )
  1625. vString.StrCat( outputFormat.GetCurrencyVectorSeparator() );
  1626. // Big enough for a 1e308 + 9 decimal places + sign
  1627. WCHAR awc[maxFloatSize];
  1628. double dblValue;
  1629. VarR8FromCy( _variant.cacy.pElems[iValue], &dblValue );
  1630. _cwcRAWValue = swprintf( awc, L"%lf", dblValue );
  1631. vString.StrCat( awc, _cwcRAWValue );
  1632. }
  1633. vString.StrCat( outputFormat.GetCurrencyVectorSuffix() );
  1634. _wcsRAWValue = vString.StrDup();
  1635. _cwcRAWValue = vString.StrLen();
  1636. }
  1637. break;
  1638. default:
  1639. {
  1640. if ( VT_ARRAY & _variant.vt )
  1641. {
  1642. VARTYPE vt = _variant.vt & ~VT_ARRAY;
  1643. if ( VT_I1 == vt || VT_UI1 == vt ||
  1644. VT_I2 == vt || VT_UI2 == vt ||
  1645. VT_I4 == vt || VT_UI4 == vt ||
  1646. VT_INT == vt || VT_UINT == vt ||
  1647. VT_I8 == vt || VT_UI8 == vt ||
  1648. VT_R4 == vt || VT_R8 == vt ||
  1649. VT_CY == vt || VT_DECIMAL == vt ||
  1650. VT_ERROR == vt )
  1651. _eNumType = eRawNumber;
  1652. CVirtualString vString( 0x200 );
  1653. RenderSafeArray( vt,
  1654. _variant.parray,
  1655. outputFormat,
  1656. vString,
  1657. FALSE );
  1658. _wcsRAWValue = vString.StrDup();
  1659. _cwcRAWValue = vString.StrLen();
  1660. }
  1661. else
  1662. {
  1663. _wcsRAWValue = _wcsNumberValue;
  1664. *_wcsRAWValue = 0;
  1665. _cwcRAWValue = 0;
  1666. ciGibDebugOut(( DEB_WARN,
  1667. "Type %u not supported in out column",
  1668. _variant.vt ));
  1669. }
  1670. }
  1671. break;
  1672. }
  1673. }
  1674. #if (DBG == 1)
  1675. if ( _wcsRAWValue != 0 )
  1676. {
  1677. Win4Assert( wcslen(_wcsRAWValue) == _cwcRAWValue );
  1678. }
  1679. #endif // DBG == 1
  1680. Win4Assert( !(_wcsRAWValue == 0 && _cwcRAWValue != 0) );
  1681. cwcValue = _cwcRAWValue;
  1682. return _wcsRAWValue;
  1683. }
  1684. //+---------------------------------------------------------------------------
  1685. //
  1686. // Member: CVariable::DupStringValue - public
  1687. //
  1688. // Synopsis: Makes a copy of the string value of this variable
  1689. //
  1690. // Returns: A pointer to a string representation of the variable's value.
  1691. //
  1692. // History: 96/Mar/07 DwightKr Created.
  1693. //
  1694. //----------------------------------------------------------------------------
  1695. WCHAR * CVariable::DupStringValue( COutputFormat & outputFormat )
  1696. {
  1697. ULONG cwcValue;
  1698. WCHAR * wcsValue = GetStringValueRAW( outputFormat, cwcValue );
  1699. WCHAR * wcsCopyOfValue = new WCHAR[ cwcValue + 1 ];
  1700. RtlCopyMemory( wcsCopyOfValue,
  1701. wcsValue,
  1702. (cwcValue+1) * sizeof(WCHAR) );
  1703. return wcsCopyOfValue;
  1704. }
  1705. //+---------------------------------------------------------------------------
  1706. //
  1707. // Member: CVariable::IsDirectlyComparable - public
  1708. //
  1709. // Synopsis: Not all VT types are are numbers. This is useful when
  1710. // attempting to compare different VT_TYPES.
  1711. //
  1712. // Returns: TRUE if the variable can be represented as a number, FALSE
  1713. // for strings, blobs, etc.
  1714. //
  1715. // History: 96/Jan/03 DwightKr Created.
  1716. //
  1717. //----------------------------------------------------------------------------
  1718. BOOL CVariable::IsDirectlyComparable() const
  1719. {
  1720. switch ( _variant.vt & ( ~VT_VECTOR ) )
  1721. {
  1722. case VT_UI1:
  1723. case VT_I1:
  1724. case VT_UI2:
  1725. case VT_I2:
  1726. case VT_UI4:
  1727. case VT_I4:
  1728. case VT_UINT:
  1729. case VT_INT:
  1730. case VT_R4:
  1731. case VT_R8:
  1732. case VT_I8:
  1733. case VT_UI8:
  1734. case VT_BOOL:
  1735. case VT_CY:
  1736. case VT_DATE:
  1737. case VT_FILETIME:
  1738. case VT_DECIMAL:
  1739. return TRUE;
  1740. }
  1741. return FALSE;
  1742. }
  1743. //+---------------------------------------------------------------------------
  1744. //
  1745. // Member: CVariableSet::SetVariable - public
  1746. //
  1747. // Synopsis: A assignment operator; allows the value of a variable to
  1748. // be changed.
  1749. //
  1750. // Arguments: [wcsName] - the variable name
  1751. // [pVariant] - new value for this variable
  1752. // [ulCreateFlags] - and flags associated with this variable;
  1753. // such as requiring an IRowsetScroll
  1754. //
  1755. // History: 96/Jan/03 DwightKr Created.
  1756. // 96/Apr/11 DwightKr Set back link
  1757. //
  1758. //----------------------------------------------------------------------------
  1759. CVariable * CVariableSet::SetVariable( WCHAR const * wcsName,
  1760. PROPVARIANT const * pVariant,
  1761. ULONG ulCreateFlags )
  1762. {
  1763. Win4Assert( 0 != wcsName );
  1764. ULONG ulHash = ISAPIVariableNameHash( wcsName );
  1765. CVariable *pVariable = Find(wcsName, ulHash);
  1766. if ( 0 != pVariable )
  1767. {
  1768. pVariable->SetValue( pVariant, ulCreateFlags );
  1769. }
  1770. else
  1771. {
  1772. pVariable = new CVariable( wcsName,
  1773. pVariant,
  1774. ulCreateFlags );
  1775. pVariable->SetNext( _variableSet[ ulHash ] );
  1776. if ( 0 != pVariable->GetNext() )
  1777. {
  1778. pVariable->GetNext()->SetBack( pVariable );
  1779. }
  1780. _variableSet[ ulHash ] = pVariable;
  1781. }
  1782. return pVariable;
  1783. }
  1784. //+---------------------------------------------------------------------------
  1785. //
  1786. // Member: CVariableSet::CopyStringValue - public
  1787. //
  1788. // Synopsis: A assignment operator; allows the value of a variable to
  1789. // be changed.
  1790. //
  1791. // Arguments: [wcsName] - the variable name
  1792. // [wcsValue] - value of the variable
  1793. // [ulCreateFlags] - and flags associated with this variable;
  1794. // such as requiring an IRowsetScroll
  1795. // [cwcValue] - # of chars in wcsValue or 0 if unknown
  1796. //
  1797. // History: 96/Jan/03 DwightKr Created.
  1798. //
  1799. //----------------------------------------------------------------------------
  1800. void CVariableSet::CopyStringValue( WCHAR const * wcsName,
  1801. WCHAR const * wcsValue,
  1802. ULONG ulCreateFlags,
  1803. ULONG cwcValue )
  1804. {
  1805. Win4Assert( 0 != wcsName );
  1806. Win4Assert( 0 != wcsValue );
  1807. if ( 0 == cwcValue )
  1808. cwcValue = wcslen( wcsValue );
  1809. cwcValue++;
  1810. XArray<WCHAR> wcsCopyOfValue( cwcValue );
  1811. RtlCopyMemory( wcsCopyOfValue.Get(), wcsValue, cwcValue * sizeof(WCHAR) );
  1812. PROPVARIANT propVariant;
  1813. propVariant.vt = VT_LPWSTR;
  1814. propVariant.pwszVal = wcsCopyOfValue.Get();
  1815. SetVariable( wcsName, &propVariant, ulCreateFlags | eParamOwnsVariantMemory );
  1816. wcsCopyOfValue.Acquire();
  1817. }
  1818. //+---------------------------------------------------------------------------
  1819. //
  1820. // Member: CVariableSet::AcquireStringValue - public
  1821. //
  1822. // Synopsis: A assignment operator; allows the value of a variable to
  1823. // be changed. Ownership of wcsValue is transferred.
  1824. //
  1825. // Arguments: [wcsName] - the variable name
  1826. // [wcsValue] - value of this variable
  1827. // [ulCreateFlags] - and flags associated with this variable;
  1828. //
  1829. // History: 96/Jan/03 DwightKr Created.
  1830. //
  1831. //----------------------------------------------------------------------------
  1832. void CVariableSet::AcquireStringValue( WCHAR const * wcsName,
  1833. WCHAR * wcsValue,
  1834. ULONG ulCreateFlags )
  1835. {
  1836. Win4Assert( 0 != wcsName );
  1837. Win4Assert( 0 != wcsValue );
  1838. PROPVARIANT propVariant;
  1839. propVariant.vt = VT_LPWSTR;
  1840. propVariant.pwszVal = wcsValue;
  1841. SetVariable( wcsName, &propVariant, ulCreateFlags | eParamOwnsVariantMemory );
  1842. }
  1843. void CVariableSet::SetVariable( WCHAR const * wcsName,
  1844. XArray<WCHAR> & xValue )
  1845. {
  1846. Win4Assert( 0 != wcsName );
  1847. Win4Assert( 0 != xValue.Get() );
  1848. PROPVARIANT propVariant;
  1849. propVariant.vt = VT_LPWSTR;
  1850. propVariant.pwszVal = xValue.Get();
  1851. SetVariable( wcsName, &propVariant, eParamOwnsVariantMemory );
  1852. xValue.Acquire();
  1853. }
  1854. //+---------------------------------------------------------------------------
  1855. //
  1856. // Member: CVariableSet::AddVariableSet - public
  1857. //
  1858. // Synopsis: Adds all variables in the variableSet to this variableSet.
  1859. //
  1860. // Arguments: [variableSet] - the variableSet to add
  1861. //
  1862. // History: 96/Jan/03 DwightKr Created.
  1863. //
  1864. //----------------------------------------------------------------------------
  1865. void CVariableSet::AddVariableSet( CVariableSet & variableSet,
  1866. COutputFormat & outputFormat )
  1867. {
  1868. for ( CVariableSetIter iter(variableSet);
  1869. !iter.AtEnd();
  1870. iter.Next()
  1871. )
  1872. {
  1873. CVariable * pVariable = iter.Get();
  1874. SetVariable( pVariable->GetName(),
  1875. pVariable->GetValue(),
  1876. pVariable->GetFlags() );
  1877. }
  1878. }
  1879. //+---------------------------------------------------------------------------
  1880. //
  1881. // Member: CVariableSet::CVariableSet - copy constructor
  1882. //
  1883. // Synopsis: makes a copy of the variableSet
  1884. //
  1885. // Arguments: [variableSet] - the variableSet to copy
  1886. //
  1887. // History: 96/Jan/03 DwightKr Created.
  1888. // 96/Apr/11 DwightKr Set back link
  1889. //
  1890. //----------------------------------------------------------------------------
  1891. CVariableSet::CVariableSet( const CVariableSet & variableSet )
  1892. {
  1893. RtlZeroMemory( _variableSet, sizeof _variableSet );
  1894. for ( CVariableSetIter iter(variableSet);
  1895. !iter.AtEnd();
  1896. iter.Next()
  1897. )
  1898. {
  1899. CVariable * pVariable = iter.Get();
  1900. CVariable * pNewVariable = new CVariable( *pVariable );
  1901. XPtr<CVariable> xNewVariable(pNewVariable);
  1902. ULONG ulHash = ISAPIVariableNameHash( pNewVariable->GetName() );
  1903. //
  1904. // Set NEXT & BACK pointers in the hash chain
  1905. //
  1906. pNewVariable->SetNext( _variableSet[ ulHash ] );
  1907. if ( 0 != pNewVariable->GetNext() )
  1908. {
  1909. pNewVariable->GetNext()->SetBack( pNewVariable );
  1910. }
  1911. _variableSet[ ulHash ] = pNewVariable;
  1912. xNewVariable.Acquire();
  1913. }
  1914. }
  1915. //+---------------------------------------------------------------------------
  1916. //
  1917. // Member: CVariableSet::GetValue - public
  1918. //
  1919. // Synopsis: Gets the value of the variable whose name is specified.
  1920. //
  1921. // Arguments: [wcsName] - the variable name to return a value for
  1922. //
  1923. // Returns: PROPVARIANT * to the variable, 0 if no variable with this name.
  1924. //
  1925. // History: 96/Jan/03 DwightKr Created.
  1926. //
  1927. //----------------------------------------------------------------------------
  1928. PROPVARIANT * CVariableSet::GetValue( WCHAR const * wcsName ) const
  1929. {
  1930. CVariable * pVariable = Find( wcsName );
  1931. if ( pVariable )
  1932. return pVariable->GetValue();
  1933. else
  1934. return 0;
  1935. }
  1936. //+---------------------------------------------------------------------------
  1937. //
  1938. // Member: CVariableSet::GetStringValueRAW - public
  1939. //
  1940. // Synopsis: Gets the string value of the variable whose name is specified.
  1941. //
  1942. // Arguments: [wcsName] - the variable name to return a value for
  1943. //
  1944. // Returns: WCHAR * to the variable's string representation, 0 if no
  1945. // variable with this name.
  1946. //
  1947. // History: 96/Jan/03 DwightKr Created.
  1948. //
  1949. //----------------------------------------------------------------------------
  1950. WCHAR const * CVariableSet::GetStringValueRAW( WCHAR const * wcsName,
  1951. ULONG ulHash,
  1952. COutputFormat & outputFormat,
  1953. ULONG & cwcValue )
  1954. {
  1955. CVariable * pVariable = Find(wcsName, ulHash);
  1956. if ( pVariable )
  1957. return pVariable->GetStringValueRAW( outputFormat, cwcValue );
  1958. else
  1959. return 0;
  1960. }
  1961. //+---------------------------------------------------------------------------
  1962. //
  1963. // Member: CVariableSet::AddExtensionControlBlock
  1964. //
  1965. // Synopsis: Adds QUERY_STRING or STDIN buffer to variable set
  1966. //
  1967. // Arguments: [webServer] - extension control block to add to variableSet
  1968. //
  1969. // History: 03-Jan-96 DwightKr Created.
  1970. // 11-Jun-97 KyleP Take codepage from web server
  1971. // 11-Sep-98 KLam Assert that method is GET or POST
  1972. //
  1973. //----------------------------------------------------------------------------
  1974. void CVariableSet::AddExtensionControlBlock( CWebServer & webServer )
  1975. {
  1976. //
  1977. // Determine if the user has passed the variables via a GET or POST
  1978. //
  1979. //
  1980. // We support only the GET and POST methods
  1981. //
  1982. BYTE * pszBuffer;
  1983. ULONG cbBuffer;
  1984. XArray<BYTE> xTemp;
  1985. if ( strcmp( webServer.GetMethod(), "GET" ) == 0 )
  1986. {
  1987. pszBuffer = (BYTE *) webServer.GetQueryString();
  1988. cbBuffer = strlen( (char *)pszBuffer );
  1989. }
  1990. else if ( strcmp( webServer.GetMethod(), "POST" ) == 0 )
  1991. {
  1992. pszBuffer = (BYTE *) webServer.GetClientData( cbBuffer );
  1993. // posts aren't null terminated, and we expect them to be.
  1994. xTemp.Init( cbBuffer + 1 );
  1995. RtlCopyMemory( xTemp.GetPointer(), pszBuffer, cbBuffer );
  1996. xTemp[cbBuffer] = 0;
  1997. pszBuffer = xTemp.Get();
  1998. }
  1999. else
  2000. {
  2001. //
  2002. // The validity of the method should have been checked before
  2003. //
  2004. Win4Assert ( strcmp( webServer.GetMethod(), "GET" ) == 0
  2005. || strcmp( webServer.GetMethod(), "POST" ) == 0);
  2006. }
  2007. ciGibDebugOut(( DEB_ITRACE, "QUERY_STRING = %s\n", pszBuffer ));
  2008. // NOTE: The pszBuffer is pointing to strings in the ECB. We
  2009. // shouldn't modify these strings.
  2010. if ( cbBuffer > 0 )
  2011. {
  2012. //
  2013. // Strip off trailing control characters, such as \n\r
  2014. //
  2015. while ( (cbBuffer > 0) && (pszBuffer[cbBuffer-1] <= ' ') )
  2016. {
  2017. cbBuffer--;
  2018. }
  2019. //
  2020. // Setup the QUERY_STRING variable in our variableSet
  2021. //
  2022. XArray<WCHAR> wcsQueryString;
  2023. ULONG cwcBuffer = MultiByteToXArrayWideChar( (BYTE * const) pszBuffer,
  2024. cbBuffer + 1,
  2025. webServer.CodePage(),
  2026. wcsQueryString );
  2027. Win4Assert( cwcBuffer != 0 && cwcBuffer <= (cbBuffer+1) );
  2028. wcsQueryString[ cwcBuffer ] = L'\0';
  2029. PROPVARIANT Variant;
  2030. Variant.vt = VT_LPWSTR;
  2031. Variant.pwszVal = wcsQueryString.Get();
  2032. SetVariable( ISAPI_QUERY_STRING, &Variant, eParamOwnsVariantMemory );
  2033. wcsQueryString.Acquire();
  2034. }
  2035. //
  2036. // Parse the string, which has the following format:
  2037. //
  2038. //
  2039. // attr1=Value1&attr2=value2&attr3=value+%7c+0&foo&bar
  2040. //
  2041. CHAR * pszToken = (CHAR *)pszBuffer;
  2042. while ( (0 != pszToken) && (0 != *pszToken) )
  2043. {
  2044. //
  2045. // Find the value on the right hand side of the equal sign.
  2046. //
  2047. CHAR *pszAttribute = pszToken;
  2048. CHAR *pszValue = strchr( pszAttribute, '=' );
  2049. if ( 0 != pszValue )
  2050. {
  2051. ULONG cchAttribute = (ULONG)(pszValue - pszAttribute);
  2052. pszValue++;
  2053. //
  2054. // Point to the next attribute.
  2055. //
  2056. pszToken = strchr( pszToken, '&' );
  2057. ULONG cchValue;
  2058. if ( 0 != pszToken )
  2059. {
  2060. if ( pszToken < pszValue )
  2061. {
  2062. //
  2063. // We have a construction like foo&bar=value. Skip the
  2064. // 'foo' part.
  2065. //
  2066. pszToken++;
  2067. continue;
  2068. }
  2069. cchValue = (ULONG)(pszToken - pszValue);
  2070. pszToken++;
  2071. }
  2072. else
  2073. {
  2074. cchValue = (ULONG)((CHAR *)&pszBuffer[cbBuffer] - pszValue);
  2075. }
  2076. WCHAR wcsAttribute[200];
  2077. if ( cchAttribute >= ( sizeof wcsAttribute / sizeof WCHAR ) )
  2078. THROW( CException( DB_E_ERRORSINCOMMAND ) );
  2079. DecodeURLEscapes( (BYTE *) pszAttribute, cchAttribute, wcsAttribute,
  2080. webServer.CodePage() );
  2081. if ( 0 == cchAttribute )
  2082. THROW( CException( DB_E_ERRORSINCOMMAND ) );
  2083. DecodeHtmlNumeric( wcsAttribute );
  2084. //
  2085. // We could use Win32 for uppercasing the string, but we're looking for a fixed
  2086. // set of attributes that are known to be in this character set.
  2087. //
  2088. _wcsupr( wcsAttribute );
  2089. XArray<WCHAR> wcsValue( cchValue+2 );
  2090. DecodeURLEscapes( (BYTE *) pszValue, cchValue, wcsValue.Get(), webServer.CodePage() );
  2091. if ( 0 != cchValue )
  2092. {
  2093. DecodeHtmlNumeric( wcsValue.Get() );
  2094. }
  2095. ciGibDebugOut(( DEB_ITRACE, "From browser, setting %ws=%ws\n",
  2096. wcsAttribute,
  2097. wcsValue.Get() ));
  2098. SetVariable( wcsAttribute, wcsValue );
  2099. }
  2100. else if ( 0 != pszToken )
  2101. {
  2102. //
  2103. // There was no attribute=value pair found; a lonely '&' was
  2104. // found. Skip it and proceed to the next '&'.
  2105. //
  2106. pszToken = strchr( pszToken+1, '&' );
  2107. }
  2108. }
  2109. }
  2110. //+---------------------------------------------------------------------------
  2111. //
  2112. // Member: ISAPIVariableNameHash - public
  2113. //
  2114. // Synopsis: Generates a hash for the name specified
  2115. //
  2116. // Arguments: [pwcName] - the variable name to hash
  2117. //
  2118. // Returns: ULONG - hash of the name
  2119. //
  2120. // History: 96/Jan/03 DwightKr Created.
  2121. //
  2122. //
  2123. //----------------------------------------------------------------------------
  2124. ULONG ISAPIVariableNameHash( WCHAR const * pwcName )
  2125. {
  2126. Win4Assert( 0 != pwcName );
  2127. WCHAR const *pwcStart = pwcName;
  2128. ULONG ulHash = 0;
  2129. while ( 0 != *pwcName )
  2130. {
  2131. ulHash <<= 1;
  2132. ulHash += *pwcName;
  2133. pwcName++;
  2134. }
  2135. ulHash <<= 1;
  2136. ulHash += (ULONG)( pwcName - pwcStart );
  2137. return ulHash % VARIABLESET_HASH_TABLE_SIZE;
  2138. }
  2139. //+---------------------------------------------------------------------------
  2140. //
  2141. // Member: CVariableSet::~CVariableSet - public
  2142. //
  2143. // Synopsis: Deletes the variables in the set.
  2144. //
  2145. // History: 96/Apr/03 dlee Created.
  2146. //
  2147. //
  2148. //----------------------------------------------------------------------------
  2149. CVariableSet::~CVariableSet()
  2150. {
  2151. // Variables delete the next in their chain, so only delete the
  2152. // start of each hash chain.
  2153. for ( unsigned x = 0; x < VARIABLESET_HASH_TABLE_SIZE; x++ )
  2154. delete _variableSet[ x ];
  2155. }
  2156. //+---------------------------------------------------------------------------
  2157. //
  2158. // Member: CVariableSet::Find
  2159. //
  2160. // Synopsis: Locates a variable in the variableSet with the given name
  2161. //
  2162. // Arguments: [wcsName] - name of variable to find
  2163. // [ulHash] - hashed value of the name
  2164. //
  2165. // Returns: pVariable if found, 0 otherwise
  2166. //
  2167. // History: 96/Apr/11 DwightKr Created.
  2168. //
  2169. //----------------------------------------------------------------------------
  2170. CVariable * CVariableSet::Find( WCHAR const * wcsName, ULONG ulHash ) const
  2171. {
  2172. Win4Assert( ulHash == ISAPIVariableNameHash(wcsName) );
  2173. //
  2174. // Walk down the chain and try to find a match
  2175. // Note: Variable names have been converted to upper case before
  2176. // we got this far. Hence, the case insensitive string
  2177. // comparison.
  2178. //
  2179. for ( CVariable * pVariable = _variableSet[ ulHash ];
  2180. pVariable != 0;
  2181. pVariable = pVariable->GetNext()
  2182. )
  2183. {
  2184. Win4Assert( pVariable != 0);
  2185. if ( wcscmp(wcsName, pVariable->GetName() ) == 0 )
  2186. {
  2187. return pVariable;
  2188. }
  2189. }
  2190. return 0;
  2191. }
  2192. //+---------------------------------------------------------------------------
  2193. //
  2194. // Member: CVariableSet::Delete
  2195. //
  2196. // Synopsis: Deletes a single variable from a variableSet
  2197. //
  2198. // Arguments: [pVariable] - pointer to variable to delete
  2199. //
  2200. // History: 96/Apr/11 DwightKr Created.
  2201. //
  2202. //----------------------------------------------------------------------------
  2203. void CVariableSet::Delete( CVariable * pVariable )
  2204. {
  2205. Win4Assert ( 0 != pVariable );
  2206. ULONG ulHash = ISAPIVariableNameHash( pVariable->GetName() );
  2207. Win4Assert( Find(pVariable->GetName(), ulHash) == pVariable );
  2208. //
  2209. // If there is a variable before this one in the hash chain, set its
  2210. // next pointer.
  2211. //
  2212. if ( 0 != pVariable->GetBack() )
  2213. {
  2214. pVariable->GetBack()->SetNext( pVariable->GetNext() );
  2215. }
  2216. //
  2217. // If there is a variable after this one in the hash chain, set its
  2218. // back pointer.
  2219. //
  2220. if ( 0 != pVariable->GetNext() )
  2221. {
  2222. pVariable->GetNext()->SetBack( pVariable->GetBack() );
  2223. }
  2224. //
  2225. // Update the array
  2226. //
  2227. if ( _variableSet[ulHash] == pVariable )
  2228. {
  2229. _variableSet[ulHash] = pVariable->GetNext();
  2230. }
  2231. pVariable->SetNext(0);
  2232. pVariable->SetBack(0);
  2233. delete pVariable;
  2234. }
  2235. #if (DBG == 1)
  2236. //+---------------------------------------------------------------------------
  2237. //
  2238. // Member: CVariableSet::Dump
  2239. //
  2240. // Synopsis: Appends each of the variables to the virtual string supplied
  2241. //
  2242. // Arguments: [string] - string to append data to
  2243. //
  2244. // History: 96/Jan/03 DwightKr Created.
  2245. //
  2246. //----------------------------------------------------------------------------
  2247. void CVariableSet::Dump( CVirtualString & wcsString,
  2248. COutputFormat & outputFormat )
  2249. {
  2250. for (CVariableSetIter iter(*this);
  2251. !iter.AtEnd();
  2252. iter.Next() )
  2253. {
  2254. CVariable *pVariable = iter.Get();
  2255. wcsString.StrCat( pVariable->GetName() );
  2256. wcsString.CharCat( L'=' );
  2257. ULONG cwcValue;
  2258. WCHAR * wcsValue = pVariable->GetStringValueRAW( outputFormat, cwcValue);
  2259. wcsString.StrCat( wcsValue, cwcValue );
  2260. wcsString.StrCat( L"<BR>\n" );
  2261. }
  2262. }
  2263. #endif // DBG == 1