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.

228 lines
5.7 KiB

  1. /*
  2. Copyright (c) 1997-1999 Microsoft Corporation
  3. */
  4. #include "sdppch.h"
  5. #include "sdpsarr.h"
  6. inline void
  7. IncrementIndices(
  8. IN ULONG NumSafeArrays,
  9. IN OUT LONG *Index
  10. )
  11. {
  12. for (ULONG i=0; i < NumSafeArrays; i++)
  13. {
  14. Index[i]++;
  15. }
  16. }
  17. inline ULONG
  18. MinSize(
  19. IN const ULONG NumSafeArrays,
  20. IN VARIANT *Variant[]
  21. )
  22. {
  23. ULONG ReturnValue = 0;
  24. for (UINT i=0; i < NumSafeArrays; i++)
  25. {
  26. if ( ReturnValue < V_ARRAY(Variant[i])->rgsabound[0].cElements )
  27. {
  28. ReturnValue = V_ARRAY(Variant[i])->rgsabound[0].cElements;
  29. }
  30. }
  31. return ReturnValue;
  32. }
  33. BOOL
  34. SDP_SAFEARRAY::CreateAndAttach(
  35. IN ULONG MinSize,
  36. IN VARTYPE VarType,
  37. IN OUT VARIANT &Variant,
  38. OUT HRESULT &HResult
  39. )
  40. {
  41. // create a 1 based 1 dimensional safearray
  42. SAFEARRAYBOUND rgsabound[1];
  43. rgsabound[0].lLbound = 1;
  44. rgsabound[0].cElements = MinSize;
  45. SAFEARRAY *SafeArray = SafeArrayCreate(VarType, 1, rgsabound);
  46. if ( NULL == SafeArray )
  47. {
  48. HResult = E_OUTOFMEMORY;
  49. return FALSE;
  50. }
  51. // set the variant type
  52. V_VT(&Variant) = VT_ARRAY | VarType;
  53. V_ARRAY(&Variant) = SafeArray;
  54. // attach the variant to the instance
  55. Attach(Variant);
  56. HResult = S_OK;
  57. return TRUE;
  58. }
  59. HRESULT
  60. SDP_SAFEARRAY_WRAP::GetSafeArrays(
  61. IN const ULONG NumElements,
  62. IN const ULONG NumSafeArrays,
  63. IN VARTYPE VarType[],
  64. OUT VARIANT *Variant[]
  65. )
  66. {
  67. if ( 0 == NumElements )
  68. {
  69. return HRESULT_FROM_ERROR_CODE(ERROR_INVALID_DATA);
  70. }
  71. // clear each of the variants (it may not be a safearray)
  72. for(ULONG Index=0; Index < NumSafeArrays; Index++)
  73. {
  74. BAIL_IF_NULL(Variant[Index], E_INVALIDARG);
  75. BAIL_ON_FAILURE(VariantClear(Variant[Index]));
  76. }
  77. try
  78. {
  79. DYNAMIC_POINTER_ARRAY<SDP_SAFEARRAY> SdpSafeArray(NumSafeArrays);
  80. for (ULONG j=0; j < NumSafeArrays; j++)
  81. {
  82. HRESULT HResult;
  83. // create 1 based one-dimensional safearrays
  84. if ( !SdpSafeArray[j].CreateAndAttach(NumElements, VarType[j], *(Variant[j]), HResult) )
  85. {
  86. for (ULONG k=0; k < j; k++)
  87. {
  88. HRESULT FreeResult;
  89. if ( !SdpSafeArray[k].Free(FreeResult) )
  90. {
  91. return FreeResult;
  92. }
  93. }
  94. return HResult;
  95. }
  96. }
  97. // for each element in the attribute list, add the bstr
  98. // to the safe array
  99. // the indexing begins at 1 (1 based one-dimensional array)
  100. LONG Index = 1;
  101. DYNAMIC_ARRAY<void *> Element(NumSafeArrays);
  102. for( ULONG i= 0; i < NumElements; i++, Index++ )
  103. {
  104. HRESULT HResult;
  105. if ( !GetElement(i, NumSafeArrays, Element(), HResult) )
  106. {
  107. return HResult;
  108. }
  109. // assign the list element to the ith safe array element
  110. for (j=0; j < NumSafeArrays; j++)
  111. {
  112. SdpSafeArray[j].PutElement(&Index, Element[j]);
  113. }
  114. }
  115. }
  116. catch(COleException &OleException)
  117. {
  118. // *** convert the SCODE to HRESULT
  119. return ResultFromScode(OleException.Process(&OleException));
  120. }
  121. return S_OK;
  122. }
  123. HRESULT
  124. SDP_SAFEARRAY_WRAP::SetSafeArrays(
  125. IN const ULONG NumSafeArrays,
  126. IN VARTYPE VarType[],
  127. IN VARIANT *Variant[]
  128. )
  129. {
  130. // validate parameter
  131. for ( ULONG j=0; j < NumSafeArrays; j++ )
  132. {
  133. if ( !ValidateSafeArray(VarType[j], Variant[j]) )
  134. {
  135. return E_INVALIDARG;
  136. }
  137. }
  138. try
  139. {
  140. DYNAMIC_POINTER_ARRAY<SDP_SAFEARRAY> SdpSafeArray(NumSafeArrays);
  141. for (j=0; j < NumSafeArrays; j++)
  142. {
  143. SdpSafeArray[j].Attach(*(Variant[j]));
  144. }
  145. // while there are elements in the list, set bstrs
  146. // if no corresponding element in the list, create and add a new one
  147. DYNAMIC_ARRAY<LONG> Index(NumSafeArrays);
  148. for (j=0; j < NumSafeArrays; j++)
  149. {
  150. Index[j] = V_ARRAY(Variant[j])->rgsabound[0].lLbound;
  151. }
  152. DYNAMIC_ARRAY<void **> Element(NumSafeArrays);
  153. // need only consider the number of items in the smallest sized safearray
  154. ULONG MinSafeArraySize = MinSize(NumSafeArrays, Variant);
  155. // *** currently not checking that all safe arrays have the same number of non-null
  156. // elements
  157. for ( ULONG i = 0;
  158. i < MinSafeArraySize;
  159. i++, IncrementIndices(NumSafeArrays, Index())
  160. )
  161. {
  162. for (j=0; j < NumSafeArrays; j++)
  163. {
  164. SdpSafeArray[j].PtrOfIndex(&Index[j], (void **)&Element[j]);
  165. }
  166. HRESULT HResult;
  167. // grow the list if required
  168. if ( !SetElement(i, NumSafeArrays, Element(), HResult) )
  169. {
  170. // success means that there are no more elements in the safe array
  171. if ( SUCCEEDED(HResult) )
  172. {
  173. break;
  174. }
  175. else
  176. {
  177. return HResult;
  178. }
  179. }
  180. }
  181. // get rid of each list element that is in excess of the safearray members
  182. RemoveExcessElements(i);
  183. }
  184. catch(COleException &OleException)
  185. {
  186. // *** convert the SCODE to HRESULT
  187. return ResultFromScode(OleException.Process(&OleException));
  188. }
  189. return S_OK;
  190. }