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.

843 lines
27 KiB

  1. //+-------------------------------------------------------------------------
  2. //
  3. // Microsoft Windows
  4. // Copyright (C) Microsoft Corporation, 1992 - 2000.
  5. //
  6. // File: TableCol.cxx
  7. //
  8. // Contents: Large table column descriptors
  9. //
  10. // Classes: CTableColumn
  11. // CTableColumnArray
  12. // CTableColumnSet
  13. //
  14. // History: 15 Sep 94 AlanW Split from coldesc.cxx
  15. //
  16. //--------------------------------------------------------------------------
  17. #include "pch.cxx"
  18. #pragma hdrstop
  19. #include <tablecol.hxx>
  20. #include <tblvarnt.hxx>
  21. #include "colcompr.hxx"
  22. #include "tabledbg.hxx"
  23. #include "pathstor.hxx"
  24. IMPL_DYNARRAY( CTableColumnArray, CTableColumn );
  25. //+-------------------------------------------------------------------------
  26. //
  27. // Member: CTableColumn::~CTableColumn, public
  28. //
  29. // Synopsis: Destructor for a table column description.
  30. //
  31. // Notes:
  32. //
  33. //--------------------------------------------------------------------------
  34. CTableColumn::~CTableColumn( )
  35. {
  36. if (_pCompression && !_fGlobalCompr && _CompressMasterID == 0)
  37. delete _pCompression;
  38. }
  39. //+-------------------------------------------------------------------------
  40. //
  41. // Member: CTableColumnSet::Add, public
  42. //
  43. // Synopsis: Add a column description to a column set.
  44. //
  45. // Arguments: [pCol] - a smart pointer to column to be added.
  46. // [iCol] - position in array to use.
  47. //
  48. // Returns: Nothing
  49. //
  50. // Notes: Care is taken to assure that the smart pointer is
  51. // transferred to the column array without generating
  52. // an exception while holding the bare pointer.
  53. //
  54. //--------------------------------------------------------------------------
  55. void
  56. CTableColumnSet::Add(
  57. XPtr<CTableColumn> & pCol,
  58. unsigned iCol
  59. ) {
  60. if (iCol >= Size())
  61. CTableColumnArray::Add(0, iCol); // probe to expand array
  62. CTableColumnArray::Add(pCol.Acquire(), iCol);
  63. if (iCol >= Count())
  64. {
  65. Win4Assert(iCol == Count());
  66. SetCount(iCol+1);
  67. }
  68. }
  69. // CLEANCODE - old version, delete me someday
  70. void
  71. CTableColumnSet::Add(
  72. CTableColumn* pCol,
  73. unsigned iCol
  74. ) {
  75. CTableColumnArray::Add(pCol, iCol);
  76. if (iCol >= Count())
  77. {
  78. Win4Assert(iCol == Count());
  79. SetCount(iCol+1);
  80. }
  81. }
  82. //+-------------------------------------------------------------------------
  83. //
  84. // Member: CTableColumnSet::Find, public
  85. //
  86. // Synopsis: Find a particular column in a column array
  87. //
  88. // Arguments: [PropId] - property ID to search for
  89. // [rfFound] - reference to flag, set to TRUE if match found
  90. //
  91. // Returns: CTableColumn* - pointer to the column found, or zero
  92. //
  93. // Notes:
  94. //
  95. //--------------------------------------------------------------------------
  96. CTableColumn *
  97. CTableColumnSet::Find(
  98. PROPID const PropId,
  99. BOOL& rfFound
  100. ) const {
  101. for (unsigned i=0; i<Count(); i++) {
  102. CTableColumn* pCol = Get(i);
  103. if (pCol && pCol->PropId == PropId) {
  104. rfFound = TRUE;
  105. return pCol;
  106. }
  107. }
  108. rfFound = FALSE;
  109. return 0;
  110. }
  111. //+-------------------------------------------------------------------------
  112. //
  113. // Member: CTableColumnSet::Marshall, public
  114. //
  115. // Synopsis: Serialize a table column set
  116. //
  117. // Arguments: [stm] - serialization stream
  118. // [pids] - CPidMapper to convert propids for propspecs
  119. //
  120. // Returns: Nothing
  121. //
  122. //--------------------------------------------------------------------------
  123. void CTableColumnSet::Marshall(
  124. PSerStream & stm,
  125. CPidMapper & pids
  126. ) const {
  127. stm.PutULong(Count());
  128. for (unsigned i = 0; i < Count(); i++)
  129. Get(i)->Marshall( stm, pids );
  130. }
  131. //+-------------------------------------------------------------------------
  132. //
  133. // Member: CTableColumn::Marshall, public
  134. //
  135. // Synopsis: Serialize a table column
  136. //
  137. // Arguments: [stm] - serialization stream
  138. // [pids] - CPidMapper to convert propids for propspecs
  139. //
  140. // Returns: Nothing
  141. //
  142. //--------------------------------------------------------------------------
  143. void CTableColumn::Marshall(
  144. PSerStream & stm,
  145. CPidMapper & pids
  146. ) const {
  147. pids.PidToName(PropId)->Marshall( stm );
  148. stm.PutULong(GetStoredType());
  149. if ( 0 == IsValueStored() )
  150. stm.PutByte( FALSE );
  151. else
  152. {
  153. stm.PutByte( TRUE );
  154. stm.PutUShort( GetValueOffset() );
  155. stm.PutUShort( GetValueSize() );
  156. }
  157. if ( 0 == IsStatusStored() )
  158. stm.PutByte( FALSE );
  159. else
  160. {
  161. stm.PutByte( TRUE );
  162. stm.PutUShort( GetStatusOffset() );
  163. // stm.PutUShort( GetStatusSize() );
  164. }
  165. if ( 0 == IsLengthStored() )
  166. stm.PutByte( FALSE );
  167. else
  168. {
  169. stm.PutByte( TRUE );
  170. stm.PutUShort( GetLengthOffset() );
  171. // stm.PutUShort( GetLengthSize() );
  172. }
  173. }
  174. //+-------------------------------------------------------------------------
  175. //
  176. // Member: CTableColumnSet::CTableColumnSet, public
  177. //
  178. // Synopsis: Construct a table column set from a serialized stream
  179. //
  180. // Arguments: [stm] - serialization stream
  181. // [pids] - CPidMapper to convert propspecs to fake pids
  182. //
  183. // Returns: Nothing
  184. //
  185. //--------------------------------------------------------------------------
  186. CTableColumnSet::CTableColumnSet( PDeSerStream & stm, CPidMapper & pidmap )
  187. : _cColumns(0),
  188. CTableColumnArray( 0 )
  189. {
  190. ULONG cItems = stm.GetULong();
  191. // Guard against attack
  192. if ( cItems > 1000 )
  193. THROW( CException( E_INVALIDARG ) );
  194. SetExactSize( cItems );
  195. for ( unsigned i = 0; i < cItems; i++ )
  196. {
  197. CFullPropSpec prop( stm );
  198. if ( !prop.IsValid() )
  199. THROW( CException( E_OUTOFMEMORY ) );
  200. PROPID pid = pidmap.NameToPid( prop );
  201. XPtr<CTableColumn> Col( new CTableColumn( pid ) );
  202. DBTYPE DataType = (USHORT) stm.GetULong();
  203. //
  204. // Only support VT_VARIANT and VT_I4 bindings. Other ones aren't
  205. // tested or officially supported -- our OLE DB client only uses
  206. // these two. Other datatypes are probably a hacker.
  207. //
  208. if ( VT_I4 == DataType )
  209. {
  210. // VT_I4 must be workid
  211. if ( ! ( ( prop.IsPropertyPropid() ) &&
  212. ( prop.GetPropertyPropid() == PROPID_QUERY_WORKID ) &&
  213. ( prop.GetPropSet() == PSGUID_QUERY ) ) )
  214. THROW( CException( E_INVALIDARG ) );
  215. }
  216. else if ( VT_VARIANT != DataType )
  217. THROW( CException( E_INVALIDARG ) );
  218. if ( TRUE == stm.GetByte() )
  219. {
  220. USHORT usOffset = stm.GetUShort();
  221. // Check for a bogus offset
  222. if ( usOffset > 0x1000 )
  223. THROW( CException( E_INVALIDARG ) );
  224. // validate the offset
  225. Col->SetValueField ( DataType, usOffset, stm.GetUShort() );
  226. }
  227. if ( TRUE == stm.GetByte() )
  228. {
  229. USHORT usOffset = stm.GetUShort();
  230. // Check for a bogus offset
  231. if ( usOffset > 0x1000 )
  232. THROW( CException( E_INVALIDARG ) );
  233. Col->SetStatusField ( usOffset, sizeof (BYTE) );
  234. }
  235. if ( TRUE == stm.GetByte() )
  236. {
  237. USHORT usOffset = stm.GetUShort();
  238. // Check for a bogus offset
  239. if ( usOffset > 0x1000 )
  240. THROW( CException( E_INVALIDARG ) );
  241. Col->SetLengthField ( usOffset, sizeof (ULONG) );
  242. }
  243. Add( Col.Acquire(), i);
  244. }
  245. }
  246. //+---------------------------------------------------------------------------
  247. //
  248. // Function: _IsSpecialPathProcessing
  249. //
  250. // Synopsis: Tests if the column is a candidate for doing special path
  251. // processing or not.
  252. //
  253. // Arguments: [dstColumn] - The column into which the data must be copied
  254. // in the destination row.
  255. //
  256. // Returns: TRUE if special path processing can be done.
  257. // FALSE o/w
  258. //
  259. // History: 5-23-95 srikants Created
  260. //
  261. // Notes:
  262. //
  263. //----------------------------------------------------------------------------
  264. inline
  265. BOOL
  266. CTableColumn::_IsSpecialPathProcessing( CTableColumn const & dstColumn ) const
  267. {
  268. VARTYPE vtDst = dstColumn.GetStoredType();
  269. return ( pidPath == PropId || pidName == PropId ) &&
  270. ( vtDst == VT_LPWSTR ) &&
  271. ( _StoreAsType == VT_LPWSTR ) &&
  272. ( _pCompression != 0);
  273. }
  274. //+---------------------------------------------------------------------------
  275. //
  276. // Function: _GetPathOrFile
  277. //
  278. // Synopsis: Fetches the path or file (if possible) using special processing
  279. // in the path store (if possible).
  280. //
  281. // Arguments: [dstColumn] - Destination column into which the data is
  282. // being copied.
  283. // [pbSrc] - The source window row.
  284. // [rDstPool] - Var allocator for destination variable memory
  285. // allocation.
  286. // [pbDstRow] - Pointer to the destination row.
  287. //
  288. // Returns: TRUE if the pidName/pidPath could be fetched. FALSE o/w.
  289. //
  290. // History: 5-23-95 srikants Created
  291. //
  292. // Notes:
  293. //
  294. //----------------------------------------------------------------------------
  295. BOOL CTableColumn::_GetPathOrFile( CTableColumn const & dstColumn,
  296. const BYTE * pbSrc,
  297. PVarAllocator & rDstPool,
  298. BYTE * pbDstRow
  299. )
  300. {
  301. const BYTE * pbSrcOrg = pbSrc;
  302. CPathStore * pSrcPathStore = 0;
  303. if ( 0 != _pCompression )
  304. {
  305. pSrcPathStore = _pCompression->GetPathStore();
  306. }
  307. if ( 0 == pSrcPathStore )
  308. return FALSE;
  309. // tbDebugOut(( DEB_ITRACE, "Special Path Processing\n" ));
  310. //
  311. // We have a path store.
  312. //
  313. Win4Assert( GetValueSize() == sizeof(PATHID) );
  314. pbSrc += GetValueOffset();
  315. PATHID srcPathId;
  316. RtlCopyMemory( &srcPathId, pbSrc, sizeof(PATHID) );
  317. BOOL fDone = FALSE;
  318. if ( !dstColumn.IsCompressedCol() )
  319. {
  320. //
  321. // Extract the path/file out of the path store for this pathid.
  322. //
  323. WCHAR * pwszDest = pSrcPathStore->Get( srcPathId, PropId, rDstPool );
  324. if ( 0 != pwszDest )
  325. {
  326. ULONG_PTR offset = rDstPool.PointerToOffset( pwszDest );
  327. Win4Assert( dstColumn.GetValueSize() == sizeof(ULONG) );
  328. RtlCopyMemory( pbDstRow + dstColumn.GetValueOffset(),
  329. &offset,
  330. dstColumn.GetValueSize() );
  331. Win4Assert( dstColumn.IsStatusStored() );
  332. dstColumn.SetStatus( pbDstRow, GetStatus( pbSrcOrg ) );
  333. if ( dstColumn.IsLengthStored() )
  334. {
  335. ULONG *pulLength = (ULONG *)
  336. (pbDstRow + dstColumn.GetLengthOffset());
  337. *pulLength = (ULONG) (wcslen( pwszDest ) + 1 ) * sizeof(WCHAR);
  338. }
  339. fDone = TRUE;
  340. }
  341. }
  342. else
  343. {
  344. //
  345. // The destination column is compressed. See if it
  346. // also has a path store and copy to it.
  347. //
  348. Win4Assert( dstColumn.IsValueStored() );
  349. //
  350. // Copy the data to the target.
  351. //
  352. if ( 0 == dstColumn.GetCompressMasterId() )
  353. {
  354. Win4Assert( dstColumn.IsStatusStored() );
  355. dstColumn.SetStatus( pbDstRow, GetStatus( pbSrcOrg ) );
  356. CPathStore * pDstPathStore =
  357. dstColumn.GetCompressor()->GetPathStore();
  358. ULONG* pulRowColDataBuf = dstColumn.GetValueSize() ?
  359. (ULONG*) (pbDstRow + dstColumn.GetValueOffset()) :
  360. 0;
  361. Win4Assert( 0 != pulRowColDataBuf );
  362. if ( 0 != pDstPathStore )
  363. {
  364. *pulRowColDataBuf = pDstPathStore->AddPath( *pSrcPathStore, srcPathId );
  365. fDone = TRUE;
  366. }
  367. }
  368. else
  369. {
  370. //
  371. // This is shared compression. There is nothing to store for this
  372. // column.
  373. //
  374. fDone = TRUE;
  375. }
  376. }
  377. return fDone;
  378. }
  379. //+-------------------------------------------------------------------------
  380. //
  381. // Member: CTableColumn::CopyColumnData, public
  382. //
  383. // Synopsis: Copy a column's data fields between two row buffers.
  384. // Coercion of the data can occur for data transfer to
  385. // the user.
  386. //
  387. // Arguments: [pbDstRow] -- destination row buffer
  388. // [rDstColumn] -- destination column description
  389. // [rDstPool] -- destination variable data allocator
  390. // [pbSrcRow] -- source row buffer
  391. // [rSrcPool] -- source variable data allocator
  392. //
  393. // Returns: DBSTATUS -- status of the column copy
  394. //
  395. // History: 22 Feb 1995 AlanW Created
  396. //
  397. //--------------------------------------------------------------------------
  398. DBSTATUS CTableColumn::CopyColumnData(
  399. BYTE * pbDstRow,
  400. CTableColumn const & rDstColumn,
  401. PVarAllocator & rDstPool,
  402. BYTE * pbSrcRow,
  403. PVarAllocator & rSrcPool
  404. )
  405. {
  406. DBSTATUS DstStatus = DBSTATUS_S_OK;
  407. // pull out the data types for clarity below
  408. VARTYPE vtDst = rDstColumn.GetStoredType();
  409. VARTYPE vtSrc = GetStoredType();
  410. #if 0
  411. if (rDstColumn.IsValueStored())
  412. #endif
  413. {
  414. Win4Assert( IsValueStored() );
  415. // the row buffer promises NOT to set the byref bit for these.
  416. // we'll break elsewhere if this is not true.
  417. Win4Assert(vtSrc != ( VT_LPWSTR | VT_BYREF ) );
  418. Win4Assert(vtSrc != ( VT_LPSTR | VT_BYREF ) );
  419. Win4Assert( 0 == ( VT_VECTOR & vtDst ) );
  420. // Transfer a data value
  421. if ( ( vtDst == vtSrc ) &&
  422. ( CTableVariant::IsSimpleType( vtDst ) ) &&
  423. ! IsCompressedCol() &&
  424. ! rDstColumn.IsCompressedCol() )
  425. {
  426. // Data columns equivalent, and not indirect. Just
  427. // copy from source to dest.
  428. Win4Assert( rDstColumn.IsStatusStored() );
  429. rDstColumn.SetStatus( pbDstRow, GetStatus( pbSrcRow ) );
  430. #if CIDBG == 1 || DBG == 1
  431. USHORT cbData, cbAlignment, rgfFlags;
  432. CTableVariant::VartypeInfo(vtSrc, cbData, cbAlignment, rgfFlags);
  433. Win4Assert( CTableVariant::TableIsStoredInline( rgfFlags,
  434. vtSrc ) );
  435. Win4Assert( rDstColumn.GetValueSize() == GetValueSize() &&
  436. cbData == GetValueSize());
  437. #endif // CIDBG == 1 || DBG == 1
  438. RtlCopyMemory( pbDstRow + rDstColumn.GetValueOffset(),
  439. pbSrcRow + GetValueOffset(),
  440. GetValueSize());
  441. // performance: we never bind to length for these fixed-length
  442. // fields.
  443. Win4Assert( !rDstColumn.IsLengthStored() );
  444. //if (rDstColumn.IsLengthStored())
  445. // rDstColumn.SetLength( pbDstRow, rDstColumn.GetValueSize() );
  446. }
  447. else
  448. {
  449. //
  450. // Check if this is "pidPath"/ "pidName" and if the destination
  451. // allows special path processing.
  452. //
  453. if ( !_IsSpecialPathProcessing(rDstColumn) ||
  454. !_GetPathOrFile( rDstColumn, pbSrcRow,
  455. rDstPool, pbDstRow ) )
  456. {
  457. if ( ( vtDst == VT_LPWSTR
  458. || vtDst == ( DBTYPE_WSTR | DBTYPE_BYREF )
  459. )
  460. && vtSrc == VT_LPWSTR
  461. && !IsCompressedCol()
  462. && !rDstColumn.IsCompressedCol() )
  463. {
  464. //
  465. // Optimized path for the common case of wide string -> wide string
  466. // copy, such as paths and filenames
  467. //
  468. BYTE *pbSrc = pbSrcRow + GetValueOffset();
  469. WCHAR *pszValue = *(WCHAR **) pbSrc;
  470. BYTE *pbDestBuf = pbDstRow + rDstColumn.GetValueOffset();
  471. Win4Assert( (ULONG_PTR) pbDestBuf % 4 == 0 );
  472. if ( pszValue )
  473. {
  474. ULONG cbSrc = ( wcslen(pszValue) + 1 ) * sizeof( WCHAR );
  475. BYTE *pbDest = (BYTE *) rDstPool.CopyTo( cbSrc, (BYTE *) pszValue );
  476. *(BYTE **) pbDestBuf = (BYTE *) rDstPool.PointerToOffset( pbDest );
  477. }
  478. else
  479. {
  480. *(ULONG *) pbDestBuf = 0;
  481. }
  482. Win4Assert( !rDstColumn.IsLengthStored() );
  483. #if 0
  484. if ( rDstColumn.IsLengthStored() )
  485. {
  486. ULONG *pulLength = (ULONG *) pbDstRow + rDstColumn.GetLengthOffset();
  487. *pulLength = GetValueSize();
  488. }
  489. #endif // 0
  490. }
  491. else
  492. {
  493. //
  494. // For any other case, convert to a CTableVariant, then
  495. // copy it using the CopyOrCoerce method. This allows
  496. // coercions and variant to nonvariant, etc. conversions
  497. // to occur.
  498. //
  499. // NOTE: We may want to optimize the PROPVARIANT to PROPVARIANT
  500. // case when offsets are used in both source and
  501. // destination, since this will occur commonly in
  502. // table splits and row fetches.
  503. //
  504. CTableVariant varnt;
  505. XCompressFreeVariant xpVarnt;
  506. if ( CreateVariant(varnt, pbSrcRow, rSrcPool) )
  507. xpVarnt.Set(GetCompressor(), &varnt);
  508. if ( rDstColumn.IsCompressedCol() )
  509. {
  510. Win4Assert( rDstColumn.IsValueStored() &&
  511. ! rDstColumn.IsLengthStored() );
  512. //
  513. // Copy the data to the target.
  514. //
  515. if (0 == rDstColumn.GetCompressMasterId())
  516. {
  517. ULONG* pulRowColDataBuf = rDstColumn.GetValueSize() ?
  518. (ULONG*) (pbDstRow + rDstColumn.GetValueOffset()) :
  519. 0;
  520. GetValueResult eGvr;
  521. rDstColumn.GetCompressor()->AddData( &varnt,
  522. pulRowColDataBuf,
  523. eGvr);
  524. Win4Assert( eGvr == GVRSuccess );
  525. }
  526. }
  527. else
  528. {
  529. DBLENGTH ulTemp;
  530. DstStatus = varnt.CopyOrCoerce(
  531. pbDstRow + rDstColumn.GetValueOffset(),
  532. rDstColumn.GetValueSize(),
  533. vtDst,
  534. ulTemp,
  535. rDstPool);
  536. }
  537. if (rDstColumn.IsLengthStored())
  538. {
  539. ULONG *pulLength = (ULONG *)
  540. (pbDstRow + rDstColumn.GetLengthOffset());
  541. if (rDstColumn.GetStoredType() == VT_VARIANT)
  542. {
  543. USHORT flags,cbWidth,cbAlign;
  544. CTableVariant::VartypeInfo( varnt.vt,
  545. cbWidth,
  546. cbAlign,
  547. flags );
  548. if ( CTableVariant::TableIsStoredInline( flags,
  549. varnt.vt ) )
  550. *pulLength = (ULONG) cbWidth;
  551. else
  552. *pulLength = (ULONG) varnt.VarDataSize();
  553. }
  554. else
  555. {
  556. // PERFFIX - CopyOrCorece should supply the output length!
  557. *pulLength = GetValueSize();
  558. }
  559. }
  560. }
  561. }
  562. Win4Assert( rDstColumn.IsStatusStored() );
  563. Win4Assert( IsStatusStored() );
  564. rDstColumn.SetStatus( pbDstRow, GetStatus( pbSrcRow ) );
  565. }
  566. tbDebugOut(( DEB_ITRACE, "ColumnStatus: 0x%x\n",
  567. rDstColumn.GetStatus( pbDstRow ) ));
  568. }
  569. #if 0 // we never bind to size/length and NOT bind to value
  570. else
  571. {
  572. //
  573. // Destination doesn't need value, check to see if it needs the
  574. // length or status. Get it from the input if it's there.
  575. // Assert if the required value is not there.
  576. //
  577. // NOTE: These values will be valid only for a DBTYPE_VARIANT
  578. // result.
  579. //
  580. if (rDstColumn.IsLengthStored())
  581. {
  582. Win4Assert(VT_VARIANT == rDstColumn.GetStoredType());
  583. ULONG *pulLength = (ULONG *)
  584. (pbDstRow + rDstColumn.GetLengthOffset());
  585. if (IsLengthStored())
  586. *pulLength = *(ULONG *) (pbSrcRow + GetLengthOffset());
  587. else
  588. {
  589. Win4Assert(IsValueStored());
  590. CTableVariant varnt;
  591. XCompressFreeVariant xpVarnt;
  592. if ( CreateVariant(varnt, pbSrcRow, rSrcPool) )
  593. xpVarnt.Set(GetCompressor(), &varnt);
  594. USHORT flags,cbWidth,cbAlign;
  595. CTableVariant::VartypeInfo( varnt.vt,
  596. cbWidth,
  597. cbAlign,
  598. flags );
  599. if ( CTableVariant::TableIsStoredInline( flags, varnt.vt ) )
  600. *pulLength = (ULONG) cbWidth;
  601. else
  602. *pulLength = (ULONG) varnt.VarDataSize();
  603. }
  604. }
  605. // fill-in the column status
  606. Win4Assert( rDstColumn.IsStatusStored() );
  607. Win4Assert( IsStatusStored() );
  608. rDstColumn.SetStatus( pbDstRow, GetStatus( pbSrcRow ) );
  609. }
  610. #endif // 0: we never bind to size/length and NOT bind to value
  611. return DstStatus;
  612. } //CopyColumn
  613. //+-------------------------------------------------------------------------
  614. //
  615. // Member: CTableColumn::CreateVariant, public
  616. //
  617. // Synopsis: Create a table variant from a source column.
  618. //
  619. // Arguments: [rVarnt] -- reference to variant structure to be filled
  620. // [pbSrc] -- source row buffer
  621. // [rSrcPool] -- source variable data allocator
  622. //
  623. // Returns: BOOL -- TRUE if variant needs to be freed by
  624. // column compressor.
  625. //
  626. // Notes: CLEANCODE - Should this routine take an XCompressFreeVariant as an
  627. // input parameter to guard against memory leaks? An
  628. // argument against is that HROW buffers would never
  629. // be compressed, and don't need to know about column
  630. // compressors.
  631. //
  632. // History: 22 Feb 1995 AlanW Created
  633. //
  634. //--------------------------------------------------------------------------
  635. BOOL CTableColumn::CreateVariant(
  636. CTableVariant & rVarnt,
  637. BYTE * pbSrc,
  638. PVarAllocator & rSrcPool
  639. ) const {
  640. //
  641. // Advance the row buffer pointer to the stored value data.
  642. //
  643. Win4Assert(IsValueStored());
  644. BYTE * pbSrcRow = pbSrc;
  645. pbSrc += GetValueOffset();
  646. if ( IsCompressedCol() )
  647. {
  648. GetValueResult eGvr = GetCompressor()->GetData( &rVarnt,
  649. GetStoredType(),
  650. GetValueSize()?
  651. *((ULONG *) (pbSrc)):
  652. 0,
  653. PropId);
  654. if ( GVRSuccess != eGvr )
  655. {
  656. rVarnt.vt = VT_EMPTY;
  657. }
  658. //
  659. // Set up to free the variant when we're done with it.
  660. //
  661. return TRUE;
  662. }
  663. else
  664. {
  665. //
  666. // There is no compression.
  667. //
  668. if (VT_VARIANT == GetStoredType())
  669. {
  670. Win4Assert(GetValueSize() == sizeof PROPVARIANT);
  671. rVarnt = *((CTableVariant *) (pbSrc));
  672. }
  673. else
  674. {
  675. if ( IsNull( pbSrcRow ) )
  676. rVarnt.vt = VT_EMPTY;
  677. else
  678. rVarnt.Init( GetStoredType(), pbSrc, GetValueSize() );
  679. }
  680. if ( rVarnt.VariantPointerInFirstWord() &&
  681. GetStoredType() != VT_CLSID) // already stored as pointer
  682. {
  683. if (0 == rVarnt.pszVal)
  684. {
  685. rVarnt.vt = VT_EMPTY;
  686. tbDebugOut(( DEB_WARN,
  687. "null indirect value for propid %d\n",
  688. PropId ));
  689. }
  690. else
  691. {
  692. rVarnt.pszVal = (LPSTR)
  693. rSrcPool.OffsetToPointer((ULONG_PTR)rVarnt.pszVal);
  694. }
  695. }
  696. else if (rVarnt.VariantPointerInSecondWord())
  697. {
  698. if (0 == rVarnt.blob.pBlobData)
  699. {
  700. rVarnt.vt = VT_EMPTY;
  701. tbDebugOut(( DEB_WARN,
  702. "null indirect value for propid %d\n",
  703. PropId ));
  704. }
  705. else
  706. {
  707. rVarnt.blob.pBlobData = (BYTE *)
  708. rSrcPool.OffsetToPointer((ULONG_PTR)rVarnt.blob.pBlobData);
  709. }
  710. }
  711. } // no compression
  712. return FALSE;
  713. } // CreateVariant