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.

284 lines
6.2 KiB

  1. //////////////////////////////////////////////////////////////////////////////
  2. /*++
  3. Copyright (c) 1997 Microsoft Corporation
  4. Module Name:
  5. SortedSdoCollection.cpp
  6. Abstract:
  7. Implements the get__NewSortedEnum function.
  8. Given an ISdoCollection interface pointer and a property ID, this function
  9. gives back an IEnumVARIANT interface which can be used to iterate through
  10. the Sdo's in a sorted order.
  11. Include directly in file where needed.
  12. Author:
  13. Michael A. Maguire 05/19/98
  14. Revision History:
  15. mmaguire 05/19/98 - created
  16. sbens 05/27/98 - Always return an enumerator even if the collection does
  17. not need to be sorted.
  18. --*/
  19. //////////////////////////////////////////////////////////////////////
  20. //////////////////////////////////////////////////////////////////////////////
  21. // BEGIN INCLUDES
  22. //
  23. #include <ias.h>
  24. #include <sdoias.h>
  25. #include <vector>
  26. #include <algorithm>
  27. #include <SortedSdoCollection.h>
  28. //
  29. // END INCLUDES
  30. //////////////////////////////////////////////////////////////////////////////
  31. // VC smart pointer typedefs.
  32. _COM_SMARTPTR_TYPEDEF(ISdo, __uuidof(ISdo));
  33. _COM_SMARTPTR_TYPEDEF(ISdoCollection, __uuidof(ISdoCollection));
  34. //////////////////////////////////////////////////////////////////////////////
  35. // Functor needed for sort routine used below
  36. //////////////////////////////////////////////////////////////////////////////
  37. class MySort
  38. {
  39. public:
  40. MySort(LONG propertyID)
  41. : m_lpropertyID(propertyID) { }
  42. bool operator()(const _variant_t& x, const _variant_t& y) const throw ()
  43. {
  44. bool bReturnValue = FALSE;
  45. IDispatch * pDispatchX = NULL;
  46. IDispatch * pDispatchY = NULL;
  47. _variant_t varSequenceX;
  48. _variant_t varSequenceY;
  49. HRESULT hr;
  50. try
  51. {
  52. // Remember that we must free these.
  53. pDispatchX = (IDispatch *) (x);
  54. pDispatchY = (IDispatch *) (y);
  55. ISdoPtr spSdoX(pDispatchX);
  56. if( spSdoX == NULL )
  57. throw FALSE;
  58. ISdoPtr spSdoY(pDispatchY);
  59. if( spSdoY == NULL )
  60. throw FALSE;
  61. hr = spSdoX->GetProperty( m_lpropertyID, &varSequenceX );
  62. if( FAILED(hr ) )
  63. throw FALSE;
  64. hr = spSdoY->GetProperty( m_lpropertyID, &varSequenceY );
  65. if( FAILED(hr ) )
  66. throw FALSE;
  67. long lValX = (long) (varSequenceX);
  68. long lValY = (long) (varSequenceY);
  69. bReturnValue = (lValX < lValY);
  70. }
  71. catch(...)
  72. {
  73. // Catch all exceptions -- we'll just return FALSE.
  74. ;
  75. }
  76. if( NULL != pDispatchX )
  77. {
  78. pDispatchX->Release();
  79. }
  80. if( NULL != pDispatchY )
  81. {
  82. pDispatchY->Release();
  83. }
  84. return bReturnValue;
  85. }
  86. private:
  87. LONG m_lpropertyID;
  88. };
  89. /////////////////////////////////////////////////////////////////////////////
  90. // get__NewSortedEnum() - Get the SDO collection item enumerator
  91. /////////////////////////////////////////////////////////////////////////////
  92. HRESULT get__NewSortedEnum( ISdoCollection *pSdoCollection, IUnknown** pVal, LONG lPropertyID )
  93. {
  94. HRESULT hr = S_OK;
  95. // Don't know why get__Count takes a long but Next takes unsigned long.
  96. long lCount;
  97. unsigned long ulCountReceived;
  98. //
  99. // Check function preconditions
  100. //
  101. _ASSERT ( NULL != pSdoCollection );
  102. if( pSdoCollection == NULL )
  103. return E_POINTER;
  104. _ASSERT ( NULL != pVal );
  105. if (pVal == NULL)
  106. return E_POINTER;
  107. //
  108. // Get the underlying collection.
  109. //
  110. ISdoCollectionPtr spSdoCollection = pSdoCollection;
  111. //
  112. // We check the count of items in our collection and don't bother sorting the
  113. // enumerator if the count is zero.
  114. // This saves time and also helps us to a void a bug in the the enumerator which
  115. // causes it to fail if we call next when it is empty.
  116. //
  117. spSdoCollection->get_Count( & lCount );
  118. if( lCount <= 1 )
  119. {
  120. // No point in sorting.
  121. return spSdoCollection->get__NewEnum(pVal);
  122. }
  123. std::vector< _variant_t > vaObjects;
  124. //
  125. // Load values from the items from ISdoCollection into our local container item.
  126. //
  127. CComPtr< IUnknown > spUnknown;
  128. hr = spSdoCollection->get__NewEnum( (IUnknown **) & spUnknown );
  129. if( FAILED( hr ) || spUnknown == NULL )
  130. {
  131. return E_FAIL;
  132. }
  133. CComQIPtr<IEnumVARIANT, &IID_IEnumVARIANT> spEnumVariant(spUnknown);
  134. spUnknown.Release();
  135. if( spEnumVariant == NULL )
  136. {
  137. return E_FAIL;
  138. }
  139. CComVariant spVariant;
  140. // Get the first item.
  141. hr = spEnumVariant->Next( 1, & spVariant, &ulCountReceived );
  142. while( SUCCEEDED( hr ) && ulCountReceived == 1 )
  143. {
  144. vaObjects.push_back( spVariant );
  145. // Clear the variant of whatever it had --
  146. // this will release any data associated with it.
  147. //ISSUE: Need to make sure that each item we copy here is being AddRef'ed.
  148. // Check that copy into _variant_t is causing AddRef.
  149. spVariant.Clear();
  150. // Get the next item.
  151. hr = spEnumVariant->Next( 1, & spVariant, &ulCountReceived );
  152. }
  153. //
  154. // Now that we have the objects in our STL vector of variant's,
  155. // let's sort them.
  156. //
  157. std::sort( vaObjects.begin(), vaObjects.end(), MySort(lPropertyID) );
  158. //
  159. // Use ATL implementation of IEnumVARIANT
  160. //
  161. typedef CComEnum< IEnumVARIANT,
  162. &__uuidof(IEnumVARIANT),
  163. VARIANT,
  164. _Copy<VARIANT>,
  165. CComSingleThreadModel
  166. > EnumVARIANT;
  167. EnumVARIANT* newEnum = new (std::nothrow) CComObject<EnumVARIANT>;
  168. if (newEnum == NULL)
  169. {
  170. // ISSUE: Check that cleanup code for vector calls cleanup code for
  171. // _variant_t which should automatically call release on IDispatch pointers.
  172. return E_OUTOFMEMORY;
  173. }
  174. //
  175. // The AtlFlagCopy below should ensure that a new copy of the vector is made
  176. // which will persist in the enumerator once we've left this routine.
  177. //
  178. hr = newEnum->Init(
  179. vaObjects.begin(),
  180. vaObjects.end(),
  181. NULL,
  182. AtlFlagCopy
  183. );
  184. //
  185. // Hand out the enumerator to our consumer.
  186. //
  187. if (SUCCEEDED(hr))
  188. {
  189. // Enumerator object will be destroyed when the caller releases it.
  190. (*pVal = newEnum)->AddRef();
  191. // LEAVE!
  192. return S_OK;
  193. }
  194. //
  195. // ISSUE: Check that cleanup code for vector calls cleanup code for
  196. // _variant_t which should automatically call release on IDispatch pointers.
  197. //
  198. delete newEnum;
  199. return hr;
  200. }