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.

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