Source code of Windows XP (NT5)
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

259 lines
7.1 KiB

  1. //+---------------------------------------------------------------------------
  2. //
  3. // Microsoft Windows
  4. // Copyright (C) Microsoft Corporation, 1991-1998.
  5. //
  6. // File: PRelXpr.cxx
  7. //
  8. // Contents: Property relation expression
  9. //
  10. // Classes: CXprPropertyRelation
  11. //
  12. // History: 11-Sep-91 KyleP Created
  13. //
  14. //----------------------------------------------------------------------------
  15. #include <pch.cxx>
  16. #pragma hdrstop
  17. #include <parse.hxx>
  18. #include <objcur.hxx>
  19. #include <compare.hxx>
  20. #include <xpr.hxx>
  21. #include <strategy.hxx>
  22. //+---------------------------------------------------------------------------
  23. //
  24. // Member: CXprPropertyRelation::CXprPropertyRelation, public
  25. //
  26. // Synopsis: Create an expression used to test <prop> <relop> <const>
  27. //
  28. // Arguments: [pid] -- Property ID to be compared
  29. // [relop] -- Relational operator
  30. // [prval] -- Constant value to be compared against
  31. // [prstContentHelper] -- Content index helper
  32. //
  33. // History: 30-Oct-91 KyleP Created.
  34. //
  35. //----------------------------------------------------------------------------
  36. CXprPropertyRelation::CXprPropertyRelation( PROPID pid,
  37. ULONG relop,
  38. CStorageVariant const & prval,
  39. CRestriction * prstContentHelper )
  40. : CXpr( CXpr::NTProperty ),
  41. _xpval( pid ),
  42. _rel( relop ),
  43. _cval( prval ),
  44. _xrstContentHelper( prstContentHelper )
  45. {
  46. Win4Assert( getBaseRelop( _rel ) <= PRSomeBits );
  47. if ( ! _cval.IsValid() )
  48. {
  49. vqDebugOut(( DEB_ERROR, "ERROR: restriction with pointer value of 0\n" ));
  50. THROW( CException( QUERY_E_INVALIDRESTRICTION ) );
  51. }
  52. _relop = VariantCompare.GetRelop( _cval.Type(), _rel );
  53. if ( 0 == _relop )
  54. {
  55. vqDebugOut(( DEB_ERROR,
  56. "ERROR: Unsupported relational operator %d "
  57. "on type 0x%x\n",
  58. _rel,
  59. _cval.Type() ));
  60. THROW( CException( QUERY_E_INVALIDRESTRICTION ) );
  61. }
  62. }
  63. //+---------------------------------------------------------------------------
  64. //
  65. // Member: CXprPropertyRelation::CXprPropertyRelation, public
  66. //
  67. // Synopsis: Copy contstructor
  68. //
  69. // Arguments: [propxpr] -- Expression to copy
  70. //
  71. // History: 11-Dec-91 KyleP Created.
  72. //
  73. //----------------------------------------------------------------------------
  74. CXprPropertyRelation::CXprPropertyRelation( CXprPropertyRelation & propxpr )
  75. : CXpr( propxpr.NType(), propxpr.GetWeight() ),
  76. _xpval( propxpr._xpval ),
  77. _relop( propxpr._relop ),
  78. _cval( propxpr._cval ),
  79. _rel( propxpr._rel )
  80. {
  81. if ( !propxpr._xrstContentHelper.IsNull() )
  82. _xrstContentHelper.Set( propxpr._xrstContentHelper->Clone() );
  83. }
  84. //+---------------------------------------------------------------------------
  85. //
  86. // Member: CXprPropertyRelation::~CXprPropertyRelation, public
  87. //
  88. // Synopsis: Destroys the expression
  89. //
  90. // History: 30-Oct-91 KyleP Created.
  91. //
  92. //----------------------------------------------------------------------------
  93. CXprPropertyRelation::~CXprPropertyRelation()
  94. {
  95. }
  96. //+---------------------------------------------------------------------------
  97. //
  98. // Member: CXprPropertyRelation::Clone, public
  99. //
  100. // Returns: A copy of this node.
  101. //
  102. // Derivation: From base class CXpr, Always override in subclasses.
  103. //
  104. // History: 11-Dec-91 KyleP Created.
  105. //
  106. //----------------------------------------------------------------------------
  107. CXpr * CXprPropertyRelation::Clone()
  108. {
  109. return( new CXprPropertyRelation( *this ) );
  110. }
  111. void CXprPropertyRelation::SelectIndexing( CIndexStrategy & strategy )
  112. {
  113. //
  114. // Bounds checking is for index selection. Query properties are not
  115. // in any index.
  116. //
  117. if ( IS_CIQUERYPROPID(_xpval.Pid()) && _xpval.Pid() != pidUnfiltered )
  118. {
  119. strategy.SetUnknownBounds( _xpval.Pid() );
  120. return;
  121. }
  122. if ( ! _xrstContentHelper.IsNull() &&
  123. _xpval.Pid() != pidPath &&
  124. _xpval.Pid() != pidDirectory &&
  125. _xpval.Pid() != pidVirtualPath )
  126. {
  127. Win4Assert( _rel == PREQ || _rel == (PREQ|PRAny) || _rel == (PREQ|PRAll) );
  128. strategy.SetContentHelper( _xrstContentHelper.Acquire() );
  129. }
  130. switch ( _rel )
  131. {
  132. case PRLT:
  133. case PRLE:
  134. strategy.SetUpperBound( _xpval.Pid(), _cval );
  135. break;
  136. case PRGT:
  137. case PRGE:
  138. case PRAllBits:
  139. strategy.SetLowerBound( _xpval.Pid(), _cval );
  140. break;
  141. case PREQ:
  142. strategy.SetBounds( _xpval.Pid(), _cval, _cval );
  143. break;
  144. case PRSomeBits:
  145. //
  146. // Value must be at least as large as lowest set bit.
  147. //
  148. if ( _cval.Type() == VT_I4 )
  149. {
  150. long l = _cval;
  151. for ( unsigned lowbit = 0; l != 0; lowbit++ )
  152. l <<= 1;
  153. lowbit = 32 - lowbit;
  154. if ( lowbit > 0 )
  155. {
  156. CStorageVariant var( (long)(1 << lowbit) );
  157. strategy.SetLowerBound( _xpval.Pid(), var );
  158. }
  159. }
  160. break;
  161. case PRNE:
  162. default:
  163. strategy.SetUnknownBounds( _xpval.Pid() );
  164. break;
  165. }
  166. }
  167. //+---------------------------------------------------------------------------
  168. //
  169. // Member: CXprPropertyRelation::IsMatch, public
  170. //
  171. // Arguments: [obj] -- The object retriever. [obj] is already positioned
  172. // to the record to test.
  173. //
  174. // Returns: TRUE if the current record satisfies the relation.
  175. //
  176. // History: 30-Oct-91 KyleP Created.
  177. //
  178. //----------------------------------------------------------------------------
  179. BOOL CXprPropertyRelation::IsMatch( CRetriever & obj )
  180. {
  181. // this is an array of LONGLONGs to force 8-byte alignment
  182. LONGLONG allBuffer[ 10 ];
  183. ULONG cb = sizeof allBuffer;
  184. PROPVARIANT * ppv = (PROPVARIANT *) allBuffer;
  185. GetValueResult rc = _xpval.GetValue( obj, ppv, &cb );
  186. //
  187. // If the object is too big for the stack then allocate heap (sigh).
  188. //
  189. XArray<BYTE> xTemp;
  190. if ( rc == GVRNotEnoughSpace )
  191. {
  192. xTemp.Init( cb );
  193. ppv = (PROPVARIANT *) xTemp.GetPointer();
  194. rc = _xpval.GetValue( obj, ppv, &cb );
  195. }
  196. if ( rc != GVRSuccess )
  197. {
  198. vqDebugOut(( DEB_TRACE,
  199. "CXprPropertyRelation::IsMatch -- Can't get value.\n" ));
  200. return FALSE;
  201. }
  202. //
  203. // In general, the types must match for values to match.
  204. // There are exceptions for the vector case, and for != comparisons.
  205. //
  206. if ( ppv->vt != _cval.Type() )
  207. {
  208. // If != comparison and value is VT_EMPTY, it matches
  209. if ( PRNE == _rel && VT_EMPTY == _cval.Type() )
  210. return TRUE;
  211. // Could be a vector compare iff ppv is a vector and the
  212. // relop is any/all.
  213. // Otherwise, return that there is no match.
  214. if ( ! ( isVectorOrArray( *ppv ) && isVectorRelop( _rel ) ) )
  215. return FALSE;
  216. }
  217. Win4Assert( 0 != _relop );
  218. return _relop( *ppv, (PROPVARIANT &)_cval );
  219. }